/**
 * CRM settings query helpers — settings-crm (wave-15).
 *
 * Provides:
 *  - getCrmSettings:    read all four CRM fields from tenant_settings
 *  - updateCrmSettings: partial update of CRM fields
 *
 * Routes MUST NOT import raw Drizzle tables; they call these helpers.
 */
import { eq } from 'drizzle-orm'
import type { Db } from '../client'
import { tenantSettings } from '../schema/tenants'
import {
  DEFAULT_LEAD_SCORING_CRITERIA,
  leadScoringCriteriaSchema,
} from './lead-scoring'
import type { LeadScoringCriteria } from './lead-scoring'

// ── Types ─────────────────────────────────────────────────────────────────────

export interface PipelineStage {
  id: string
  label: string
  win_probability: number
  position: number
  terminal: boolean
}

export interface CrmSettingsRow {
  lead_scoring_enabled: boolean
  lead_scoring_criteria: LeadScoringCriteria
  pipeline_stages: PipelineStage[]
  lead_lost_reasons: string[]
}

export interface UpdateCrmSettingsInput {
  lead_scoring_enabled?: boolean
  lead_scoring_criteria?: LeadScoringCriteria
  pipeline_stages?: PipelineStage[]
  lead_lost_reasons?: string[]
}

// ── Defaults ──────────────────────────────────────────────────────────────────

export const DEFAULT_PIPELINE_STAGES: PipelineStage[] = [
  { id: 'new',         label: 'New Lead',      win_probability: 5,   position: 1, terminal: false },
  { id: 'qualified',   label: 'Qualified',     win_probability: 20,  position: 2, terminal: false },
  { id: 'proposal',    label: 'Proposal Sent', win_probability: 40,  position: 3, terminal: false },
  { id: 'negotiation', label: 'Negotiation',   win_probability: 70,  position: 4, terminal: false },
  { id: 'won',         label: 'Closed Won',    win_probability: 100, position: 5, terminal: true  },
  { id: 'lost',        label: 'Closed Lost',   win_probability: 0,   position: 6, terminal: true  },
]

export const DEFAULT_LOST_REASONS: string[] = [
  'Price too high',
  'No budget',
  'Chose competitor',
  'No response',
  'Project cancelled',
]

// ── Helpers ───────────────────────────────────────────────────────────────────

function parsePipelineStages(raw: unknown): PipelineStage[] {
  if (!Array.isArray(raw) || raw.length === 0) return DEFAULT_PIPELINE_STAGES
  return raw as PipelineStage[]
}

function parseLostReasons(raw: unknown): string[] {
  if (!Array.isArray(raw) || raw.length === 0) return DEFAULT_LOST_REASONS
  return raw as string[]
}

export function serializeCrmSettings(row: typeof tenantSettings.$inferSelect): CrmSettingsRow {
  const criteriaRaw = row.leadScoringCriteria
  const parsedCriteria = leadScoringCriteriaSchema.safeParse(criteriaRaw)
  const criteria = parsedCriteria.success ? parsedCriteria.data : DEFAULT_LEAD_SCORING_CRITERIA

  return {
    lead_scoring_enabled: row.leadScoringEnabled,
    lead_scoring_criteria: criteria,
    pipeline_stages: parsePipelineStages(row.pipelineStages),
    lead_lost_reasons: parseLostReasons(row.leadLostReasons),
  }
}

// ── Queries ───────────────────────────────────────────────────────────────────

/** Returns whether lead scoring is active for the tenant (defaults true when unset). */
export async function isLeadScoringEnabled(db: Db, tenantId: string): Promise<boolean> {
  const [row] = await db
    .select({ leadScoringEnabled: tenantSettings.leadScoringEnabled })
    .from(tenantSettings)
    .where(eq(tenantSettings.tenantId, tenantId))
    .limit(1)

  return row?.leadScoringEnabled ?? true
}

export async function getCrmSettings(db: Db, tenantId: string): Promise<CrmSettingsRow> {
  const row = await db
    .select()
    .from(tenantSettings)
    .where(eq(tenantSettings.tenantId, tenantId))
    .limit(1)
    .then((rows) => rows[0])

  if (!row) {
    return {
      lead_scoring_enabled: true,
      lead_scoring_criteria: DEFAULT_LEAD_SCORING_CRITERIA,
      pipeline_stages: DEFAULT_PIPELINE_STAGES,
      lead_lost_reasons: DEFAULT_LOST_REASONS,
    }
  }

  return serializeCrmSettings(row)
}

export async function updateCrmSettings(
  db: Db,
  tenantId: string,
  input: UpdateCrmSettingsInput,
): Promise<CrmSettingsRow> {
  const patch: Partial<typeof tenantSettings.$inferInsert> = {
    updatedAt: new Date(),
  }

  if (input.lead_scoring_enabled !== undefined) {
    patch.leadScoringEnabled = input.lead_scoring_enabled
  }
  if (input.lead_scoring_criteria !== undefined) {
    patch.leadScoringCriteria = input.lead_scoring_criteria
  }
  if (input.pipeline_stages !== undefined) {
    patch.pipelineStages = input.pipeline_stages
  }
  if (input.lead_lost_reasons !== undefined) {
    patch.leadLostReasons = input.lead_lost_reasons
  }

  const [updated] = await db
    .update(tenantSettings)
    .set(patch)
    .where(eq(tenantSettings.tenantId, tenantId))
    .returning()

  if (!updated) {
    throw new Error(`tenant_settings row not found for tenant ${tenantId}`)
  }

  return serializeCrmSettings(updated)
}
