package database

import (
	"database/sql"
	"fmt"
	"log"

	"golang.org/x/crypto/bcrypt"
)

func runMigrations(db *sql.DB) error {
	migrations := []string{
		// Users table
		`CREATE TABLE IF NOT EXISTS users (
			id INTEGER PRIMARY KEY AUTOINCREMENT,
			username TEXT NOT NULL UNIQUE,
			password_hash TEXT NOT NULL,
			created_at DATETIME DEFAULT CURRENT_TIMESTAMP
		)`,

		// Customers table
		`CREATE TABLE IF NOT EXISTS customers (
			id INTEGER PRIMARY KEY AUTOINCREMENT,
			name TEXT NOT NULL,
			email TEXT NOT NULL DEFAULT '',
			phone TEXT NOT NULL DEFAULT '',
			address TEXT NOT NULL DEFAULT '',
			created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
			updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
		)`,

		// Orders table
		`CREATE TABLE IF NOT EXISTS orders (
			id INTEGER PRIMARY KEY AUTOINCREMENT,
			customer_id INTEGER NOT NULL,
			status TEXT NOT NULL DEFAULT 'draft',
			order_date DATE NOT NULL DEFAULT (date('now')),
			total_amount REAL NOT NULL DEFAULT 0,
			notes TEXT NOT NULL DEFAULT '',
			created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
			updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
			FOREIGN KEY (customer_id) REFERENCES customers(id)
		)`,

		// Order lines table
		`CREATE TABLE IF NOT EXISTS order_lines (
			id INTEGER PRIMARY KEY AUTOINCREMENT,
			order_id INTEGER NOT NULL,
			description TEXT NOT NULL,
			quantity REAL NOT NULL DEFAULT 1,
			unit_price REAL NOT NULL DEFAULT 0,
			line_total REAL NOT NULL DEFAULT 0,
			FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE
		)`,

		// Invoices table
		`CREATE TABLE IF NOT EXISTS invoices (
			id INTEGER PRIMARY KEY AUTOINCREMENT,
			order_id INTEGER,
			customer_id INTEGER NOT NULL,
			invoice_number TEXT NOT NULL UNIQUE,
			status TEXT NOT NULL DEFAULT 'pending',
			amount REAL NOT NULL DEFAULT 0,
			due_date DATE NOT NULL,
			paid_date DATE,
			created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
			FOREIGN KEY (order_id) REFERENCES orders(id),
			FOREIGN KEY (customer_id) REFERENCES customers(id)
		)`,

		// GL Accounts table (Chart of Accounts)
		`CREATE TABLE IF NOT EXISTS gl_accounts (
			id INTEGER PRIMARY KEY AUTOINCREMENT,
			code TEXT NOT NULL UNIQUE,
			name TEXT NOT NULL,
			type TEXT NOT NULL,
			balance REAL NOT NULL DEFAULT 0,
			created_at DATETIME DEFAULT CURRENT_TIMESTAMP
		)`,

		// Journal Entries table
		`CREATE TABLE IF NOT EXISTS journal_entries (
			id INTEGER PRIMARY KEY AUTOINCREMENT,
			entry_date DATE NOT NULL DEFAULT (date('now')),
			description TEXT NOT NULL,
			reference TEXT NOT NULL DEFAULT '',
			created_at DATETIME DEFAULT CURRENT_TIMESTAMP
		)`,

		// Journal Lines table
		`CREATE TABLE IF NOT EXISTS journal_lines (
			id INTEGER PRIMARY KEY AUTOINCREMENT,
			journal_entry_id INTEGER NOT NULL,
			account_id INTEGER NOT NULL,
			debit REAL NOT NULL DEFAULT 0,
			credit REAL NOT NULL DEFAULT 0,
			FOREIGN KEY (journal_entry_id) REFERENCES journal_entries(id) ON DELETE CASCADE,
			FOREIGN KEY (account_id) REFERENCES gl_accounts(id)
		)`,
	}

	for i, m := range migrations {
		if _, err := db.Exec(m); err != nil {
			return fmt.Errorf("migration %d failed: %w", i, err)
		}
	}

	log.Println("Migrations completed")
	return nil
}

func seedData(db *sql.DB) error {
	// Seed admin user if not exists
	var count int
	db.QueryRow("SELECT COUNT(*) FROM users").Scan(&count)
	if count == 0 {
		hash, err := bcrypt.GenerateFromPassword([]byte("admin123"), bcrypt.DefaultCost)
		if err != nil {
			return fmt.Errorf("hashing password: %w", err)
		}
		_, err = db.Exec("INSERT INTO users (username, password_hash) VALUES (?, ?)", "admin", string(hash))
		if err != nil {
			return fmt.Errorf("inserting admin user: %w", err)
		}
		log.Println("Seeded admin user (admin / admin123)")
	}

	// Seed Chart of Accounts if not exists
	db.QueryRow("SELECT COUNT(*) FROM gl_accounts").Scan(&count)
	if count == 0 {
		accounts := []struct {
			Code, Name, Type string
		}{
			// Assets
			{"1000", "Cash", "asset"},
			{"1100", "Accounts Receivable", "asset"},
			{"1200", "Inventory", "asset"},
			// Liabilities
			{"2000", "Accounts Payable", "liability"},
			{"2100", "Sales Tax Payable", "liability"},
			// Equity
			{"3000", "Owner's Equity", "equity"},
			{"3100", "Retained Earnings", "equity"},
			// Revenue
			{"4000", "Sales Revenue", "revenue"},
			{"4100", "Service Revenue", "revenue"},
			// Expenses
			{"5000", "Cost of Goods Sold", "expense"},
			{"5100", "Salaries Expense", "expense"},
			{"5200", "Rent Expense", "expense"},
			{"5300", "Utilities Expense", "expense"},
		}

		for _, a := range accounts {
			_, err := db.Exec("INSERT INTO gl_accounts (code, name, type) VALUES (?, ?, ?)", a.Code, a.Name, a.Type)
			if err != nil {
				return fmt.Errorf("inserting account %s: %w", a.Code, err)
			}
		}
		log.Println("Seeded chart of accounts")
	}

	return nil
}
