import type {
  AccountHealth,
  OutcomeEvent,
  OutcomeSummary,
  WeeklyCheckup,
  Workspace,
} from "../../domain/types";
import type { GrowthRepo } from "../repos";
import { apiRequest } from "./http";

function mapOutcome(raw: Record<string, unknown>): OutcomeEvent {
  return {
    id: String(raw.id ?? ""),
    source_type: String(raw.source_type ?? ""),
    source_id: String(raw.source_id ?? ""),
    threads_account_id: raw.threads_account_id ? String(raw.threads_account_id) : undefined,
    kind: String(raw.kind ?? ""),
    confidence: String(raw.confidence ?? ""),
    status: String(raw.status ?? ""),
    reply_count_delta: Number(raw.reply_count_delta ?? 0),
    like_count_delta: Number(raw.like_count_delta ?? 0),
    followers_delta: Number(raw.followers_delta ?? 0),
    conversion_amount: Number(raw.conversion_amount ?? 0),
    conversion_note: raw.conversion_note ? String(raw.conversion_note) : undefined,
    conversion_currency: raw.conversion_currency ? String(raw.conversion_currency) : undefined,
    window_ends_at: Number(raw.window_ends_at ?? 0),
    sent_at: Number(raw.sent_at ?? 0),
    created_at: Number(raw.created_at ?? 0),
    updated_at: Number(raw.updated_at ?? 0),
  };
}

function mapSummary(raw: Record<string, unknown>): OutcomeSummary {
  return {
    from: Number(raw.from ?? 0),
    to: Number(raw.to ?? 0),
    reach: Number(raw.reach ?? 0),
    conversations: Number(raw.conversations ?? 0),
    follows_possible: Number(raw.follows_possible ?? 0),
    follows_confirmed: Number(raw.follows_confirmed ?? 0),
    conversions: Number(raw.conversions ?? 0),
    conversion_amount: Number(raw.conversion_amount ?? 0),
  };
}

function outcomeSummaryQuery(range: string): string {
  const now = new Date();
  let start: Date | null = null;
  if (range === "week") {
    start = new Date(now);
    const daysSinceMonday = (now.getDay() + 6) % 7;
    start.setDate(now.getDate() - daysSinceMonday);
    start.setHours(0, 0, 0, 0);
  } else if (range === "month") {
    start = new Date(now.getFullYear(), now.getMonth(), 1);
  }
  if (!start) return `range=${encodeURIComponent(range)}`;
  const from = Math.trunc(start.getTime()) * 1_000_000;
  const to = Math.trunc(now.getTime()) * 1_000_000;
  return `from=${from}&to=${to}`;
}

function mapCheckup(raw: Record<string, unknown>): WeeklyCheckup {
  const findingsRaw = Array.isArray(raw.findings) ? raw.findings : [];
  const actionsRaw = Array.isArray(raw.actions) ? raw.actions : [];
  return {
    id: String(raw.id ?? ""),
    week_key: String(raw.week_key ?? ""),
    status: String(raw.status ?? ""),
    summary: String(raw.summary ?? ""),
    findings: findingsRaw.map((f) => {
      const row = f as Record<string, unknown>;
      return {
        claim: String(row.claim ?? ""),
        evidence: Array.isArray(row.evidence) ? row.evidence.map(String) : [],
      };
    }),
    actions: actionsRaw.map((a) => {
      const row = a as Record<string, unknown>;
      return {
        title: String(row.title ?? ""),
        reason: String(row.reason ?? ""),
        deeplink: String(row.deeplink ?? "today"),
      };
    }),
    error: raw.error ? String(raw.error) : undefined,
    created_at: Number(raw.created_at ?? 0),
    updated_at: Number(raw.updated_at ?? 0),
  };
}

export function createLiveGrowthRepo(): GrowthRepo {
  return {
    async getOutcomeSummary(range = "week") {
      const data = await apiRequest<Record<string, unknown>>(
        `/api/v1/outcomes/summary?${outcomeSummaryQuery(range)}`,
      );
      return mapSummary(data);
    },
    async listOutcomes(page = 1, pageSize = 20) {
      const data = await apiRequest<{ list?: Record<string, unknown>[] }>(
        `/api/v1/outcomes?page=${page}&pageSize=${pageSize}`,
      );
      return (data.list ?? []).map(mapOutcome);
    },
    async reportConversion(id, amount, note, currency) {
      const data = await apiRequest<Record<string, unknown>>(
        `/api/v1/outcomes/${encodeURIComponent(id)}/conversion`,
        {
          method: "POST",
          body: { amount: amount ?? 0, note: note ?? "", currency: currency ?? "TWD" },
        },
      );
      return mapOutcome(data);
    },
    async getLatestCheckup() {
      const data = await apiRequest<Record<string, unknown>>("/api/v1/checkups/latest");
      return mapCheckup(data);
    },
    async generateCheckupNow() {
      const data = await apiRequest<Record<string, unknown>>("/api/v1/checkups/generate", {
        method: "POST",
        body: {},
      });
      return mapCheckup(data);
    },
    async listAccountHealth() {
      const data = await apiRequest<{ list?: Record<string, unknown>[] }>("/api/v1/account-health");
      return (data.list ?? []).map((raw) => ({
        threads_account_id: String(raw.threads_account_id ?? ""),
        score: Number(raw.score ?? 0),
        level: String(raw.level ?? "normal"),
        factors: Array.isArray(raw.factors) ? raw.factors.map(String) : [],
        advice: String(raw.advice ?? ""),
        computed_at: Number(raw.computed_at ?? 0),
      })) as AccountHealth[];
    },
    async listWorkspaces() {
      const data = await apiRequest<{
        list?: Record<string, unknown>[];
        current_workspace_id?: string;
      }>("/api/v1/workspaces");
      const list = (data.list ?? []).map(mapWorkspace);
      return { list, current_workspace_id: String(data.current_workspace_id ?? "") };
    },
    async switchWorkspace(id) {
      const data = await apiRequest<{
        list?: Record<string, unknown>[];
        current_workspace_id?: string;
      }>(`/api/v1/workspaces/${encodeURIComponent(id)}/switch`, {
        method: "POST",
        body: {},
      });
      return {
        list: (data.list ?? []).map(mapWorkspace),
        current_workspace_id: String(data.current_workspace_id ?? id),
      };
    },
    async createWorkspace(name) {
      const raw = await apiRequest<Record<string, unknown>>("/api/v1/workspaces", {
        method: "POST",
        body: { name },
      });
      return mapWorkspace(raw);
    },
  };
}

function mapWorkspace(raw: Record<string, unknown>): Workspace {
  return {
    id: String(raw.id ?? ""),
    name: String(raw.name ?? ""),
    review_required: Boolean(raw.review_required),
    is_default: Boolean(raw.is_default),
    archived: Boolean(raw.archived),
    created_at: Number(raw.created_at ?? 0),
    updated_at: Number(raw.updated_at ?? 0),
  };
}
