// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package postgres

import (
	"context"
	"database/sql"
	"fmt"

	"github.com/lib/pq"
	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/database"
	"golang.org/x/pkgsite/internal/derrors"
	"golang.org/x/pkgsite/internal/stdlib"
)

// LegacyGetPackage returns the a package from the database with the corresponding
// pkgPath, modulePath and version.
//
// If version = internal.LatestVersion, the package corresponding to
// the latest matching module version will be fetched.
//
// If more than one module tie for a given dirPath and version pair, and
// modulePath = internal.UnknownModulePath, the package in the module with the
// longest module path will be fetched.
// For example, if there are
// two rows in the packages table:
// (1) path = "github.com/hashicorp/vault/api"
//     module_path = "github.com/hashicorp/vault"
// AND
// (2) path = "github.com/hashicorp/vault/api"
//     module_path = "github.com/hashicorp/vault/api"
// The latter will be returned.
//
// The returned error may be checked with
// errors.Is(err, derrors.InvalidArgument) to determine if it was caused by an
// invalid pkgPath, modulePath or version.
//
// The returned error may be checked with
// errors.Is(err, derrors.InvalidArgument) to determine if it was caused by an
// invalid path or version.
func (db *DB) LegacyGetPackage(ctx context.Context, pkgPath, modulePath, requestedVersion string) (_ *internal.LegacyVersionedPackage, err error) {
	defer derrors.Wrap(&err, "DB.LegacyGetPackage(ctx, %q, %q)", pkgPath, requestedVersion)
	if pkgPath == "" || modulePath == "" || requestedVersion == "" {
		return nil, fmt.Errorf("none of pkgPath, modulePath, or version can be empty: %w", derrors.InvalidArgument)
	}

	args := []interface{}{pkgPath}
	query := `
		SELECT
			p.path,
			p.name,
			p.synopsis,
			p.v1_path,
			p.license_types,
			p.license_paths,
			p.redistributable,
			p.documentation,
			p.goos,
			p.goarch,
			m.version,
			m.commit_time,
			m.readme_file_path,
			m.readme_contents,
			m.module_path,
		    m.source_info,
			m.redistributable,
			m.has_go_mod
		FROM
			modules m
		INNER JOIN
			packages p
		ON
			p.module_path = m.module_path
			AND m.version = p.version`

	if modulePath == internal.UnknownModulePath || modulePath == stdlib.ModulePath {
		if requestedVersion == internal.LatestVersion {
			// Only pkgPath is specified, so get the latest version of the
			// package found in any module.
			query += fmt.Sprintf(`
			WHERE
				p.path = $1
			%s
			LIMIT 1;`, orderByLatest)
		} else {
			// pkgPath and version are specified, so get that package version
			// from any module.  If it exists in multiple modules, return the
			// one with the longest path.
			query += `
			WHERE
				p.path = $1
				AND p.version = $2
			ORDER BY
				p.module_path DESC
			LIMIT 1;`
			args = append(args, requestedVersion)
		}
	} else if requestedVersion == internal.LatestVersion {
		// pkgPath and modulePath are specified, so get the latest version of
		// the package in the specified module.
		query += fmt.Sprintf(`
			WHERE
				p.path = $1
				AND p.module_path = $2
			%s
			LIMIT 1;`, orderByLatest)
		args = append(args, modulePath)
	} else {
		// pkgPath, modulePath and version were all specified. Only one
		// directory should ever match this query.
		query += `
			WHERE
				p.path = $1
				AND p.version = $2
				AND p.module_path = $3`
		args = append(args, requestedVersion, modulePath)
	}

	var (
		pkg                        internal.LegacyVersionedPackage
		licenseTypes, licensePaths []string
		docHTML                    string
	)
	row := db.db.QueryRow(ctx, query, args...)
	err = row.Scan(&pkg.Path, &pkg.Name, &pkg.Synopsis,
		&pkg.V1Path, pq.Array(&licenseTypes), pq.Array(&licensePaths), &pkg.LegacyPackage.IsRedistributable,
		database.NullIsEmpty(&docHTML), &pkg.GOOS, &pkg.GOARCH, &pkg.Version,
		&pkg.CommitTime, database.NullIsEmpty(&pkg.LegacyReadmeFilePath), database.NullIsEmpty(&pkg.LegacyReadmeContents),
		&pkg.ModulePath, jsonbScanner{&pkg.SourceInfo}, &pkg.LegacyModuleInfo.IsRedistributable,
		&pkg.HasGoMod)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil, fmt.Errorf("package %s@%s: %w", pkgPath, requestedVersion, derrors.NotFound)
		}
		return nil, fmt.Errorf("row.Scan(): %v", err)
	}
	lics, err := zipLicenseMetadata(licenseTypes, licensePaths)
	if err != nil {
		return nil, err
	}
	pkg.Licenses = lics
	pkg.DocumentationHTML = convertDocumentation(docHTML)
	if db.bypassLicenseCheck {
		pkg.IsRedistributable = true
	} else {
		pkg.RemoveNonRedistributableData()
	}
	return &pkg, nil
}
