package icao

import (
	"database/sql"
	"embed"
	"fmt"
	"io"
	"os"
	"strconv"

	_ "github.com/mattn/go-sqlite3"
)

//go:embed icao.db
var icaoFS embed.FS

// Database handles ICAO address to country lookups
type Database struct {
	db *sql.DB
}

// CountryInfo represents country information for an aircraft
type CountryInfo struct {
	Country     string `json:"country"`
	CountryCode string `json:"country_code"`
	Flag        string `json:"flag"`
}

// NewDatabase creates a new ICAO database connection
func NewDatabase() (*Database, error) {
	// Extract embedded database to a temporary file
	data, err := icaoFS.ReadFile("icao.db")
	if err != nil {
		return nil, fmt.Errorf("failed to read embedded ICAO database: %w", err)
	}

	// Create temporary file for the database
	tmpFile, err := os.CreateTemp("", "icao-*.db")
	if err != nil {
		return nil, fmt.Errorf("failed to create temporary file: %w", err)
	}
	tmpPath := tmpFile.Name()

	// Write database data to temporary file
	if _, err := io.WriteString(tmpFile, string(data)); err != nil {
		tmpFile.Close()
		os.Remove(tmpPath)
		return nil, fmt.Errorf("failed to write database to temp file: %w", err)
	}
	tmpFile.Close()

	// Open SQLite database
	db, err := sql.Open("sqlite3", tmpPath+"?mode=ro") // Read-only mode
	if err != nil {
		os.Remove(tmpPath)
		return nil, fmt.Errorf("failed to open SQLite database: %w", err)
	}

	// Test the database connection
	if err := db.Ping(); err != nil {
		db.Close()
		os.Remove(tmpPath)
		return nil, fmt.Errorf("failed to ping database: %w", err)
	}

	return &Database{db: db}, nil
}

// LookupCountry returns country information for an ICAO address
func (d *Database) LookupCountry(icaoHex string) (*CountryInfo, error) {
	if len(icaoHex) != 6 {
		return &CountryInfo{
			Country:     "Unknown",
			CountryCode: "XX",
			Flag:        "🏳️",
		}, nil
	}

	// Convert hex string to integer
	icaoInt, err := strconv.ParseInt(icaoHex, 16, 64)
	if err != nil {
		return &CountryInfo{
			Country:     "Unknown",
			CountryCode: "XX",
			Flag:        "🏳️",
		}, nil
	}

	var country, countryCode, flag string
	query := `
		SELECT country, country_code, flag 
		FROM icao_allocations 
		WHERE ? BETWEEN start_addr AND end_addr 
		LIMIT 1
	`

	err = d.db.QueryRow(query, icaoInt).Scan(&country, &countryCode, &flag)
	if err != nil {
		if err == sql.ErrNoRows {
			return &CountryInfo{
				Country:     "Unknown",
				CountryCode: "XX",
				Flag:        "🏳️",
			}, nil
		}
		return nil, fmt.Errorf("database query failed: %w", err)
	}

	return &CountryInfo{
		Country:     country,
		CountryCode: countryCode,
		Flag:        flag,
	}, nil
}

// Close closes the database connection
func (d *Database) Close() error {
	return d.db.Close()
}