import { v4 as uuidv4 } from 'uuid';
import { getDb } from './schema';
import { Job, Lead, Owner } from '../types';

// ── Jobs ──

export function insertJob(job: Job): void {
  const db = getDb();
  db.prepare(`
    INSERT INTO jobs (id, status, search_config, output_config, search_id, max_properties,
                      created_at, started_at, completed_at, error,
                      progress_total, progress_processed, progress_leads)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  `).run(
    job.id,
    job.status,
    JSON.stringify(job.searchConfig),
    JSON.stringify(job.outputConfig),
    job.searchId || null,
    job.maxProperties,
    job.createdAt,
    job.startedAt || null,
    job.completedAt || null,
    job.error || null,
    job.progress?.total || 0,
    job.progress?.processed || 0,
    job.progress?.leads || 0
  );
}

export function updateJob(job: Job): void {
  const db = getDb();
  db.prepare(`
    UPDATE jobs SET
      status = ?, search_id = ?, started_at = ?, completed_at = ?,
      error = ?, progress_total = ?, progress_processed = ?, progress_leads = ?
    WHERE id = ?
  `).run(
    job.status,
    job.searchId || null,
    job.startedAt || null,
    job.completedAt || null,
    job.error || null,
    job.progress?.total || 0,
    job.progress?.processed || 0,
    job.progress?.leads || 0,
    job.id
  );
}

export function getJobById(id: string): Job | null {
  const db = getDb();
  const row: any = db.prepare('SELECT * FROM jobs WHERE id = ?').get(id);
  if (!row) return null;
  return rowToJob(row);
}

export function getAllJobs(limit = 50): Job[] {
  const db = getDb();
  const rows: any[] = db.prepare('SELECT * FROM jobs ORDER BY created_at DESC LIMIT ?').all(limit);
  return rows.map(rowToJob);
}

function rowToJob(row: any): Job {
  return {
    id: row.id,
    status: row.status,
    searchConfig: JSON.parse(row.search_config),
    outputConfig: JSON.parse(row.output_config),
    searchId: row.search_id,
    maxProperties: row.max_properties,
    createdAt: row.created_at,
    startedAt: row.started_at,
    completedAt: row.completed_at,
    error: row.error,
    progress: {
      total: row.progress_total,
      processed: row.progress_processed,
      leads: row.progress_leads,
    },
  };
}

// ── Leads ──

export function insertLead(lead: Lead): string {
  const db = getDb();
  const leadId = lead.id || uuidv4();

  db.prepare(`
    INSERT INTO leads (id, job_id, scrape_date, property_id, property_address,
                       building_data, sales_data, debt_data, tax_data)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
  `).run(
    leadId,
    lead.jobId,
    lead.scrapeDate,
    lead.propertyId,
    lead.propertyAddress,
    lead.building ? JSON.stringify(lead.building) : null,
    lead.sales ? JSON.stringify(lead.sales) : null,
    lead.debt ? JSON.stringify(lead.debt) : null,
    lead.tax ? JSON.stringify(lead.tax) : null
  );

  // Insert owners + contacts
  if (lead.owners) {
    for (const owner of lead.owners) {
      insertOwner(leadId, owner);
    }
  }

  return leadId;
}

export function insertOwner(leadId: string, owner: Owner): string {
  const db = getDb();
  const ownerId = uuidv4();

  db.prepare('INSERT INTO owners (id, lead_id, name) VALUES (?, ?, ?)').run(
    ownerId, leadId, owner.name
  );

  // Insert phone contacts
  for (const phone of owner.phones) {
    const contactId = uuidv4();
    db.prepare('INSERT INTO contacts (id, owner_id, type, value, label) VALUES (?, ?, ?, ?, ?)').run(
      contactId, ownerId, 'phone', phone.number, phone.type
    );
  }

  // Insert email contacts
  for (const email of owner.emails) {
    const contactId = uuidv4();
    db.prepare('INSERT INTO contacts (id, owner_id, type, value, label) VALUES (?, ?, ?, ?, ?)').run(
      contactId, ownerId, 'email', email, null
    );
  }

  return ownerId;
}

export function getLeadsByJobId(jobId: string): Lead[] {
  const db = getDb();
  const rows: any[] = db.prepare('SELECT * FROM leads WHERE job_id = ?').all(jobId);

  return rows.map((row) => {
    const lead: Lead = {
      id: row.id,
      jobId: row.job_id,
      scrapeDate: row.scrape_date,
      propertyId: row.property_id,
      propertyAddress: row.property_address,
      building: row.building_data ? JSON.parse(row.building_data) : undefined,
      sales: row.sales_data ? JSON.parse(row.sales_data) : undefined,
      debt: row.debt_data ? JSON.parse(row.debt_data) : undefined,
      tax: row.tax_data ? JSON.parse(row.tax_data) : undefined,
    };

    // Load owners
    lead.owners = getOwnersByLeadId(row.id);
    return lead;
  });
}

export function getOwnersByLeadId(leadId: string): Owner[] {
  const db = getDb();
  const ownerRows: any[] = db.prepare('SELECT * FROM owners WHERE lead_id = ?').all(leadId);

  return ownerRows.map((ownerRow) => {
    const contacts: any[] = db.prepare('SELECT * FROM contacts WHERE owner_id = ?').all(ownerRow.id);
    return {
      name: ownerRow.name,
      phones: contacts
        .filter((c) => c.type === 'phone')
        .map((c) => ({ number: c.value, type: c.label || 'Unknown' })),
      emails: contacts
        .filter((c) => c.type === 'email')
        .map((c) => c.value),
    };
  });
}

/**
 * Insert all leads for a completed job into the database
 */
export function persistJobResults(job: Job, leads: Lead[]): void {
  const db = getDb();
  const transaction = db.transaction(() => {
    insertJob(job);
    for (const lead of leads) {
      insertLead(lead);
    }
  });
  transaction();
}
