'use server';

import { runMigrations } from '@/lib/postgres/migrations';
import { pgQuery } from '@/lib/postgres/client';
import { markSetupComplete } from './detection';
import { parseLicenseKey, validateLicense, saveLicenseToFile, readLicenseFromFile } from '@/lib/license/validator';
import { getMachineFingerprint } from '@/lib/license/machine-id';
import type { StoredLicense } from '@/lib/license/types';
import { createSession } from '@/lib/auth';

// ─── Step 2: Validate License Key ────────────────────────────────────────────

export async function validateLicenseAction(licenseKey: string) {
  const result = parseLicenseKey(licenseKey.trim());
  if (!result.valid || !result.payload) {
    return { valid: false as const, error: result.error ?? 'Invalid license key' };
  }

  // For local edition, supply machine fingerprint info
  const fingerprint = result.payload.edition === 'local' ? getMachineFingerprint() : null;

  return {
    valid: true as const,
    customerName: result.payload.customerName,
    edition: result.payload.edition,
    expiresAt: result.payload.expiresAt,
    maxUsers: result.payload.maxUsers,
    features: result.payload.features,
    daysRemaining: result.daysRemaining,
    fingerprint,
  };
}

// ─── Final step: Complete Setup ───────────────────────────────────────────────

export interface CompleteSetupInput {
  licenseKey: string;
  appName: string;
  appCurrency: string;
  adminUsername: string;
  adminPassword: string;
  adminDisplayName: string;
  eulaAcceptedAt: string;
  clientIp?: string;
}

export async function completeSetupAction(input: CompleteSetupInput) {
  // 1. Re-validate license
  const licenseResult = await validateLicense(input.licenseKey.trim(), true);
  if (!licenseResult.valid || !licenseResult.payload) {
    return { success: false as const, error: licenseResult.error ?? 'Invalid license' };
  }

  try {
    // 2. Run all DB migrations
    await runMigrations();

    // 3. Create admin employee (uses same raw JSONB pattern as rest of app)
    const adminId = `emp-${Date.now()}`;
    const adminRaw = {
      id: adminId,
      name: input.adminDisplayName,
      jobTitle: 'Administrator',
      role: 'admin',
      username: input.adminUsername,
      password: input.adminPassword,
      salaryType: 'monthly',
      salary: 0,
    };

    await pgQuery(
      `INSERT INTO employees (id, raw, created_at, updated_at)
       VALUES ($1, $2::jsonb, NOW(), NOW())
       ON CONFLICT (id) DO UPDATE SET raw = EXCLUDED.raw, updated_at = NOW()`,
      [adminId, JSON.stringify(adminRaw)]
    );

    // 4. Save app settings
    const settingsEntries: Record<string, unknown> = {
      appName: input.appName,
      appCurrency: input.appCurrency,
    };
    for (const [key, val] of Object.entries(settingsEntries)) {
      await pgQuery(
        `INSERT INTO settings (key, value, updated_at) VALUES ($1, $2::jsonb, NOW())
         ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW()`,
        [key, JSON.stringify(val)]
      );
    }

    // 5. Store EULA acceptance
    const eulaRecord = {
      acceptedAt: input.eulaAcceptedAt,
      clientIp: input.clientIp ?? null,
      licenseId: licenseResult.payload.licenseId,
      customerId: licenseResult.payload.customerId,
    };
    await pgQuery(
      `INSERT INTO settings (key, value, updated_at) VALUES ('eula_acceptance', $1::jsonb, NOW())
       ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW()`,
      [JSON.stringify(eulaRecord)]
    );

    // 6. Store license in file + DB
    const stored: StoredLicense = {
      key: input.licenseKey.trim(),
      activatedAt: new Date().toISOString(),
      payload: licenseResult.payload,
    };
    saveLicenseToFile(stored);
    await pgQuery(
      `INSERT INTO settings (key, value, updated_at) VALUES ('license', $1::jsonb, NOW())
       ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW()`,
      [JSON.stringify(stored)]
    );

    // 7. Mark setup complete
    await markSetupComplete();

    // 8. Create session (auto login)
    await createSession(adminId, true);

    return { success: true as const, adminId };
  } catch (err) {
    const message = err instanceof Error ? err.message : 'Setup failed';
    return { success: false as const, error: message };
  }
}
