import {
  DASHBOARD_MOCKUP_PERSONAS,
  getDashboardPersonaByUserId,
} from "./fixtures/dashboard-mockup-personas";
import { DEV_FARMER_CREDENTIALS, DEV_OTP_CODE, findFarmerCredentialByPhone } from "./dev-seed-users";
import { normalizePhone } from "./phone";
import { normalizeScore } from "./scoring-normalize";
import { UZ_REGIONS } from "./reference-data/regions";

const DEV_OTP = DEV_OTP_CODE;

const ONBOARDING_STEPS = [
  "ACCOUNT",
  "CONSENT",
  "KYC",
  "FARM_PROFILE",
  "LAND_SKETCH",
  "GIS_MAPPING",
  "CROP_PLAN",
  "FARM_ASSETS",
  "DOCUMENTS",
  "FINANCE_REQUEST",
  "REVIEW",
  "SCORING",
  "RESULT",
] as const;

type OnboardingStepKey = (typeof ONBOARDING_STEPS)[number];

interface MockUser {
  id: string;
  phone: string;
  countryCode: string;
  kycStatus: string;
}

interface MockSession {
  id: string;
  userId: string;
  countryCode: string;
  channel: string;
  currentStep: number;
  currentStepKey: OnboardingStepKey;
  status: string;
  stepData: Record<string, unknown>;
  completedSteps: OnboardingStepKey[];
  stepRecords: unknown[];
  scoringStartedAt?: number;
  scoringPhase?: "geo" | "documents" | "scoring" | "finalize";
}

interface DevMockStore {
  otpStore: Map<string, { code: string; expiresAt: number }>;
  users: Map<string, MockUser>;
  sessions: Map<string, MockSession>;
  sessionsByUser: Map<string, string>;
}

const globalForDevMock = globalThis as typeof globalThis & {
  __agnetDevMockStore?: DevMockStore;
};

function seedDevPersonas(store: DevMockStore): void {
  for (const cred of DEV_FARMER_CREDENTIALS) {
    const persona = DASHBOARD_MOCKUP_PERSONAS[cred.key];
    const user: MockUser = {
      id: cred.userId,
      phone: cred.phone,
      countryCode: "UZ",
      kycStatus: "verified",
    };
    store.users.set(user.id, user);

    const session: MockSession = {
      id: persona.sessionId ?? `sess-${cred.key}`,
      userId: user.id,
      countryCode: "UZ",
      channel: "web",
      currentStep: ONBOARDING_STEPS.length,
      currentStepKey: "RESULT",
      status: "completed",
      stepData: {},
      completedSteps: [...ONBOARDING_STEPS],
      stepRecords: [],
    };
    store.sessions.set(session.id, session);
    store.sessionsByUser.set(user.id, session.id);
  }
}

function getDevMockStore(): DevMockStore {
  if (!globalForDevMock.__agnetDevMockStore) {
    globalForDevMock.__agnetDevMockStore = {
      otpStore: new Map(),
      users: new Map(),
      sessions: new Map(),
      sessionsByUser: new Map(),
    };
    seedDevPersonas(globalForDevMock.__agnetDevMockStore);
  }
  return globalForDevMock.__agnetDevMockStore;
}

const { otpStore, users, sessions, sessionsByUser } = getDevMockStore();

function stepIndex(step: OnboardingStepKey): number {
  return ONBOARDING_STEPS.indexOf(step) + 1;
}

function nextStep(step: OnboardingStepKey): OnboardingStepKey | null {
  const idx = ONBOARDING_STEPS.indexOf(step);
  return idx < ONBOARDING_STEPS.length - 1 ? ONBOARDING_STEPS[idx + 1] : null;
}

function createId(prefix: string): string {
  return `${prefix}_${Math.random().toString(36).slice(2, 10)}`;
}

export function encodeDevToken(user: MockUser): string {
  return `dev.${Buffer.from(JSON.stringify(user)).toString("base64url")}`;
}

export function decodeDevToken(token: string): MockUser | null {
  if (!token.startsWith("dev.")) return null;
  try {
    return JSON.parse(Buffer.from(token.slice(4), "base64url").toString("utf8"));
  } catch {
    return null;
  }
}

export function handleDevAuth(
  subPath: string,
  method: string,
  body: Record<string, string> | null,
): { status: number; data: unknown } {
  if (subPath === "otp" && method === "POST") {
    const rawPhone = body?.phone;
    if (!rawPhone) return { status: 400, data: { message: "phone is required" } };
    const phone = normalizePhone(rawPhone);
    otpStore.set(phone, { code: DEV_OTP, expiresAt: Date.now() + 5 * 60 * 1000 });
    console.log(`[dev-mock] OTP for ${phone}: ${DEV_OTP}`);
    return { status: 200, data: { sent: true } };
  }

  if (subPath === "verify" && method === "POST") {
    const phone = body?.phone ? normalizePhone(body.phone) : undefined;
    const code = body?.code;
    const countryCode = body?.countryCode ?? "UZ";
    const stored = phone ? otpStore.get(phone) : undefined;

    if (!stored || stored.expiresAt < Date.now()) {
      return { status: 401, data: { message: "OTP expired or not found" } };
    }
    if (stored.code !== code) {
      return { status: 401, data: { message: "Invalid OTP" } };
    }

    otpStore.delete(phone!);

    const seeded = findFarmerCredentialByPhone(phone!);
    let user = seeded ? users.get(seeded.userId) : [...users.values()].find((u) => u.phone === phone);
    if (!user) {
      user = {
        id: createId("user"),
        phone: phone!,
        countryCode,
        kycStatus: "pending",
      };
      users.set(user.id, user);
    }

    return {
      status: 200,
      data: {
        accessToken: encodeDevToken(user),
        user,
      },
    };
  }

  if (subPath === "me" && method === "GET") {
    return { status: 401, data: { message: "Unauthorized" } };
  }

  return { status: 404, data: { message: "Not found" } };
}

export function handleDevAuthMe(token: string): { status: number; data: unknown } {
  const user = decodeDevToken(token);
  if (!user) return { status: 401, data: { message: "Unauthorized" } };

  const activeSessionId = sessionsByUser.get(user.id);
  const activeSession = activeSessionId ? sessions.get(activeSessionId) ?? null : null;

  return {
    status: 200,
    data: {
      ...user,
      farmerProfile: null,
      activeSession,
    },
  };
}

function createSession(userId: string, countryCode: string, channel: string): MockSession {
  const session: MockSession = {
    id: createId("session"),
    userId,
    countryCode,
    channel,
    currentStep: 1,
    currentStepKey: "ACCOUNT",
    status: "in_progress",
    stepData: {},
    completedSteps: [],
    stepRecords: [],
  };
  sessions.set(session.id, session);
  sessionsByUser.set(userId, session.id);
  return session;
}

export function handleDevOnboarding(
  subPath: string,
  method: string,
  body: Record<string, unknown> | null,
  userId: string,
  forceNew: boolean,
): { status: number; data: unknown } {
  if (subPath === "" && method === "POST") {
    if (!forceNew) {
      const existingId = sessionsByUser.get(userId);
      const existing = existingId ? sessions.get(existingId) : undefined;
      if (existing && existing.status !== "abandoned") {
        return { status: 200, data: existing };
      }
    }

    const countryCode = String(body?.countryCode ?? "UZ");
    const channel = String(body?.channel ?? "farmer");
    return { status: 200, data: createSession(userId, countryCode, channel) };
  }

  const parts = subPath.split("/");
  const sessionId = parts[0];
  const session = sessions.get(sessionId);
  if (!session) return { status: 404, data: { message: "Session not found" } };
  if (session.userId !== userId) return { status: 400, data: { message: "Not your session" } };

  if (parts.length === 1 && method === "GET") {
    return { status: 200, data: session };
  }

  if (parts[1] === "steps" && parts[2] && method === "PATCH") {
    const step = parts[2] as OnboardingStepKey;
    const stepData = (body?.data as Record<string, unknown>) ?? {};
    const markComplete = body?.markComplete !== false;

    session.stepData = {
      ...session.stepData,
      [step]: { ...(session.stepData[step] as Record<string, unknown> ?? {}), ...stepData },
    };

    if (markComplete && !session.completedSteps.includes(step)) {
      session.completedSteps.push(step);
      const next = nextStep(step);
      if (next) {
        session.currentStepKey = next;
        session.currentStep = stepIndex(next);
      }
    }

    if (step === "REVIEW" && markComplete) session.status = "submitted";
    if (step === "RESULT" && markComplete) session.status = "completed";

    if (step === "KYC" && stepData.wizardDeferred) {
      session.stepData.ACCOUNT = {
        ...(session.stepData.ACCOUNT as Record<string, unknown> ?? {}),
        wizardDeferred: true,
        deferredAfterStep: "KYC",
        deferredAt: String(stepData.deferredAt ?? new Date().toISOString()),
      };
    }

    return { status: 200, data: session };
  }

  if (parts[1] === "submit" && method === "POST") {
    session.status = "scoring";
    session.currentStepKey = "SCORING";
    session.currentStep = stepIndex("SCORING");
    session.scoringStartedAt = Date.now();
    session.scoringPhase = "geo";
    return { status: 200, data: session };
  }

  if (parts[1] === "status" && method === "GET") {
    const scoringData = session.stepData.SCORING as Record<string, unknown> | undefined;
    const financeData = session.stepData.FINANCE_REQUEST as Record<string, unknown> | undefined;
    const farmProfile = session.stepData.FARM_PROFILE as Record<string, unknown> | undefined;
    const primaryLang = (farmProfile?.primaryLanguage as string) ?? "uz";

    const mockDelayMs =
      process.env.PLAYWRIGHT === "1" || process.env.AGRI_ACCESS_USE_MOCK === "true"
        ? 2000
        : 6000;
    const startedAt = session.scoringStartedAt ?? 0;
    const elapsed = startedAt ? Date.now() - startedAt : Infinity;

    let scoringPhase: "geo" | "documents" | "scoring" | "finalize" | undefined;
    if (session.status === "scoring" && startedAt) {
      if (elapsed < mockDelayMs * 0.25) scoringPhase = "geo";
      else if (elapsed < mockDelayMs * 0.5) scoringPhase = "documents";
      else if (elapsed < mockDelayMs * 0.85) scoringPhase = "scoring";
      else scoringPhase = "finalize";
      session.scoringPhase = scoringPhase;
    }

    const isScored =
      session.status === "completed" ||
      (session.status === "scoring" && elapsed >= mockDelayMs);

    const rawScore = 720;
    const normalizedScore = normalizeScore(rawScore);
    const outcome = isScored ? ("eligible" as const) : null;
    const isConditional = false;

    const reasonCodes = isScored
      ? [
          { code: "RC_NDVI_ANOMALY", feature: "Vegetation health (NDVI)", contribution: 43.2, direction: "positive" },
          { code: "RC_YIELD_FORECAST", feature: "SATAI yield forecast", contribution: 38.5, direction: "positive" },
          { code: "RC_DROUGHT_INDEX", feature: "Drought risk", contribution: -22.5, direction: "negative" },
          { code: "RC_DOC_QUALITY", feature: "Document quality", contribution: 63.0, direction: "positive" },
          { code: "RC_DTI_PROXY", feature: "Debt-to-income ratio", contribution: -18.0, direction: "negative" },
        ]
      : [];

    const farmerExplanation = {
      uz: "Sun'iy yo'ldosh ma'lumotlari va hujjatlaringiz asosida kredit ballingiz ijobiy baholandi. Hosildorlik prognozi va o'simlik salomatligi kuchli tomonlaringiz.",
      ru: "На основе спутниковых данных и ваших документов кредитный балл оценён положительно. Прогноз урожайности и здоровье растений — ваши сильные стороны.",
      en: "Based on satellite data and your documents, your credit score was assessed positively.",
    };

    const satelliteImages = isScored
      ? [
          "https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/NDVI_Terra/default/2024-06-01/250m/5/20/12.png",
        ]
      : [];

    const scoringMeta = isScored
      ? {
          modelVersion: "agri-access-uz-v0.1",
          scoringSource: process.env.AGRI_ACCESS_USE_MOCK === "true" ? "agri_access" : "agri_access",
          cbuClass: 2,
          baselPd: 0.042,
          riskRating: "B",
          ifrs9Stage: 1,
          farmerExplanation,
          satelliteSummary: "NDVI 0.72 — vegetation health above regional median for Fergana Valley",
          processingDurationMs: elapsed < Infinity ? elapsed : mockDelayMs,
        }
      : undefined;

    return {
      status: 200,
      data: {
        onboardingId: session.id,
        currentStep: session.currentStepKey,
        completedSteps: session.completedSteps,
        status: session.status,
        scoringPhase: isScored ? undefined : scoringPhase,
        eligibilityOutcome: isScored ? outcome : null,
        score: isScored ? normalizedScore : null,
        financeCaseId: isScored ? `FC-${session.id.slice(-8).toUpperCase()}` : null,
        financeCaseStatus: isScored ? (isConditional ? "under_review" : "pending") : null,
        conditionalRequirements: isScored && isConditional
          ? [
              {
                code: "land_deed_update",
                label: primaryLang === "ru" ? "Обновлённый земельный документ" : "Yangilangan yer hujjati",
                description: primaryLang === "ru"
                  ? "Загрузите кадастровый номер или документ e-Ijara"
                  : "Kadastr raqami yoki e-Ijara hujjatini yuklang",
              },
            ]
          : [],
        reasonCodes,
        scoringMeta,
        satelliteImages: isScored ? satelliteImages : [],
        amountUzs: financeData?.amountUzs ?? null,
      },
    };
  }

  if (parts.length === 1 && method === "DELETE") {
    sessions.delete(sessionId);
    if (sessionsByUser.get(userId) === sessionId) {
      sessionsByUser.delete(userId);
    }
    return { status: 204, data: null };
  }

  return { status: 404, data: { message: "Not found" } };
}

export function stubDocumentUpload(
  sessionId: string,
  docType: string,
  fileName: string,
): { status: number; data: unknown } {
  const docId = createId("doc");
  return {
    status: 200,
    data: {
      documentId: docId,
      sessionId,
      docType,
      fileName,
      status: "uploaded",
      uploadedAt: new Date().toISOString(),
    },
  };
}

export function handleDevDocumentUpload(
  token: string,
  sessionId: string,
  docType: string,
  fileName: string,
): { status: number; data: unknown } {
  const user = decodeDevToken(token);
  if (!user) return { status: 401, data: { message: "Unauthorized" } };

  const session = sessions.get(sessionId);
  if (!session) return { status: 404, data: { message: "Session not found" } };
  if (session.userId !== user.id) return { status: 400, data: { message: "Not your session" } };

  const docsStep = (session.stepData.DOCUMENTS as Record<string, unknown>) ?? {};
  const uploaded = (docsStep.uploaded as Record<string, boolean>) ?? {};
  uploaded[docType] = true;
  session.stepData.DOCUMENTS = { ...docsStep, uploaded };

  if (docType === "bank_statement" || docType === "tax_receipt") {
    const existing = (docsStep.extractedFinancials as Record<string, string>) ?? {};
    session.stepData.DOCUMENTS = {
      ...session.stepData.DOCUMENTS as Record<string, unknown>,
      extractedFinancials: {
        ...existing,
        monthlyIncomeUzs: 10_750_000,
        existingLoansUzs: 2_530_000,
        accountBalanceUzs: 40_480_000,
        confidence: {
          monthlyIncomeUzs: 0.91,
          existingLoansUzs: 0.78,
          accountBalanceUzs: 0.85,
        },
      },
    };
  }

  return stubDocumentUpload(sessionId, docType, fileName);
}

export function handleDevFarmerDashboard(userId: string): { status: number; data: unknown } {
  const persona = getDashboardPersonaByUserId(userId);
  if (persona) {
    return { status: 200, data: persona };
  }

  const user = users.get(userId);
  if (!user) return { status: 401, data: { message: "Unauthorized" } };

  const sessionId = sessionsByUser.get(userId);
  const session = sessionId ? sessions.get(sessionId) : undefined;
  if (!session) {
    return {
      status: 200,
      data: {
        userId,
        phone: user.phone,
        applicationStatus: "none",
        score: null,
        eligibility: null,
      },
    };
  }

  const stepData = session.stepData;
  const farmProfile = stepData.FARM_PROFILE as Record<string, unknown> | undefined;
  const landSketch = stepData.LAND_SKETCH as { parcels?: { areaHa?: number }[] } | undefined;
  const cropPlan = stepData.CROP_PLAN as { crops?: { crop?: string; variety?: string; season?: string; expectedYield?: number; areaHa?: number }[] } | undefined;
  const farmAssets = stepData.FARM_ASSETS as { assets?: { assetType?: string; description?: string; estimatedValueUzs?: number; condition?: string }[] } | undefined;
  const financeRequest = stepData.FINANCE_REQUEST as Record<string, unknown> | undefined;
  const scoring = stepData.SCORING as Record<string, unknown> | undefined;
  const kyc = stepData.KYC as Record<string, unknown> | undefined;
  const documents = stepData.DOCUMENTS as { uploads?: unknown[] } | undefined;

  const totalLandHa =
    landSketch?.parcels?.reduce((sum, p) => sum + (p.areaHa ?? 0), 0) ?? 0;
  const uploadCount = documents?.uploads?.length ?? 0;

  const score = scoring?.score != null ? Number(scoring.score) : session.status === "completed" ? 720 : null;
  const eligibility = (scoring?.decision as string) ?? (session.status === "completed" ? "eligible" : null);

  return {
    status: 200,
    data: {
      userId,
      phone: user.phone,
      sessionId: session.id,
      applicationStatus: session.status,
      score,
      eligibility,
      finance: financeRequest
        ? {
            purpose: String(financeRequest.purpose ?? ""),
            amount: financeRequest.amountUzs != null ? String(financeRequest.amountUzs) : "",
            existingLoans:
              financeRequest.existingLoansUzs != null
                ? String(financeRequest.existingLoansUzs)
                : "",
            monthlyIncome:
              financeRequest.monthlyIncomeUzs != null
                ? String(financeRequest.monthlyIncomeUzs)
                : "",
            repaymentHistory: String(financeRequest.repaymentHistory ?? ""),
            caseId: `AGN-FIN-${session.id.slice(-8).toUpperCase()}`,
            status: session.status === "completed" ? "under_review" : "pending",
            riskPd: 0.042,
            riskRating: "B",
            ifrs9Stage: 1,
            cbuClass: 2,
            stages: [
              { label: "Application submitted", completed: true },
              { label: "Scoring complete", completed: session.status === "completed" },
            ],
          }
        : null,
      trade: cropPlan?.crops?.length
        ? {
            crops: cropPlan.crops.map((c) => ({
              crop: c.crop ?? "",
              variety: c.variety ?? "",
              season: c.season ?? "",
              expectedYield: c.expectedYield != null ? String(c.expectedYield) : "",
            })),
            buyerMatches: [],
            exportDocsComplete: false,
          }
        : null,
      identity: farmProfile
        ? {
            fullName: String(farmProfile.fullName ?? kyc?.fullNameOfficial ?? ""),
            district: String(farmProfile.district ?? ""),
            gender: String(farmProfile.gender ?? kyc?.genderOfficial ?? ""),
            kycStatus: String(kyc?.kycStatus ?? user.kycStatus ?? "pending"),
            farmSizeHa: totalLandHa > 0 ? String(totalLandHa) : "",
            landOwnership: String(farmProfile.farmerType ?? ""),
            hasGisMapping: Boolean(stepData.GIS_MAPPING),
            documentCompleteness: Math.min(100, uploadCount * 50),
          }
        : null,
      inputs: farmAssets?.assets?.length
        ? {
            assets: farmAssets.assets.map((a) => ({
              assetType: a.assetType ?? "",
              description: a.description ?? "",
              estimatedValue: a.estimatedValueUzs != null ? String(a.estimatedValueUzs) : "",
              condition: a.condition ?? "",
            })),
            recommendedInputs: [],
          }
        : null,
    },
  };
}

export function shouldFallbackToDevMock(): boolean {
  return process.env.CORE_API_USE_MOCK === "true" || process.env.PLAYWRIGHT === "1";
}

/** Non-production may fall back to mock when upstream is missing or unavailable. */
export function canFailoverToDevMock(): boolean {
  return process.env.NODE_ENV !== "production";
}

export function shouldFailoverFromUpstream(upstream: Response | null): boolean {
  return !upstream || upstream.status === 404;
}

interface MockOneIdSession {
  sessionId: string;
  pinfl: string;
  kycAssistMode: "self_serve" | "agent_assisted";
  status: "pending" | "verified";
  createdAt: string;
}

const oneIdSessions = new Map<string, MockOneIdSession>();

function mockOfficialIdentity(pinfl: string) {
  const year = 1970 + (parseInt(pinfl.slice(0, 2), 10) % 35);
  const month = String((parseInt(pinfl.slice(2, 4), 10) % 12) + 1).padStart(2, "0");
  const day = String((parseInt(pinfl.slice(4, 6), 10) % 28) + 1).padStart(2, "0");
  const genderDigit = parseInt(pinfl.slice(6, 7), 10);
  return {
    pinfl,
    fullNameOfficial: "Olimov Olim Olimovich",
    dateOfBirthOfficial: `${year}-${month}-${day}`,
    genderOfficial: genderDigit % 2 === 0 ? ("female" as const) : ("male" as const),
  };
}

export function handleDevOneIdStart(
  pinfl: string,
  redirectUri: string,
  kycAssistMode: "self_serve" | "agent_assisted" = "self_serve",
): { status: number; data: unknown } {
  if (!/^[0-9]{14}$/.test(pinfl)) {
    return { status: 400, data: { message: "PINFL must be 14 digits" } };
  }

  const sessionId = createId("oneid");
  oneIdSessions.set(sessionId, {
    sessionId,
    pinfl,
    kycAssistMode,
    status: "pending",
    createdAt: new Date().toISOString(),
  });

  const state = Buffer.from(
    JSON.stringify({ sessionId, pinfl, kycAssistMode }),
  ).toString("base64url");
  const callbackUrl = new URL(redirectUri);
  callbackUrl.searchParams.set("code", `mock_${sessionId}`);
  callbackUrl.searchParams.set("state", state);

  return {
    status: 200,
    data: {
      sessionId,
      authorizationUrl: callbackUrl.toString(),
    },
  };
}

export function handleDevOneIdCallback(
  code: string,
  state: string,
): { status: number; data: unknown } {
  if (!code.startsWith("mock_") || !state) {
    return { status: 400, data: { message: "Invalid OneID callback" } };
  }

  let statePayload: { sessionId: string; pinfl: string; kycAssistMode: "self_serve" | "agent_assisted" };
  try {
    statePayload = JSON.parse(Buffer.from(state, "base64url").toString("utf8"));
  } catch {
    return { status: 400, data: { message: "Invalid OneID state" } };
  }

  const session = oneIdSessions.get(statePayload.sessionId);
  if (!session) {
    return { status: 404, data: { message: "OneID session not found" } };
  }

  session.status = "verified";
  const official = mockOfficialIdentity(statePayload.pinfl);
  const verifiedAt = new Date().toISOString();

  return {
    status: 200,
    data: {
      session: {
        ...session,
        status: "verified",
        official,
        verifiedAt,
      },
      official,
      kycPayload: {
        nationalId: official.pinfl,
        pinfl: official.pinfl,
        idType: "national_id",
        oneIdSessionId: session.sessionId,
        fullNameOfficial: official.fullNameOfficial,
        dateOfBirthOfficial: official.dateOfBirthOfficial,
        genderOfficial: official.genderOfficial,
        kycAssistMode: session.kycAssistMode,
        kycStatus: "verified",
        verifiedAt,
      },
    },
  };
}

export function handleDevPilotKycBypass(
  pinfl: string,
  idType: string,
  kycAssistMode: "self_serve" | "agent_assisted" = "self_serve",
): { status: number; data: unknown } {
  if (!/^[0-9]{14}$/.test(pinfl)) {
    return { status: 400, data: { message: "PINFL must be 14 digits" } };
  }

  const verifiedAt = new Date().toISOString();
  return {
    status: 200,
    data: {
      kycPayload: {
        nationalId: pinfl,
        pinfl,
        idType,
        kycAssistMode,
        oneIdSessionId: `oneid_mock_${pinfl.slice(-6)}`,
        fullNameOfficial: "SARDOR KARIMOV",
        dateOfBirthOfficial: "1985-03-15",
        genderOfficial: "male",
        kycStatus: "verified",
        verifiedAt,
      },
    },
  };
}

const CONSENT_TYPE_OPTIONS = [
  {
    value: "credit_check",
    label: "Kredit tekshiruvi va fermer ma'lumotlariga asoslangan baholashga roziman",
    metadata: { labelRu: "Согласен на проверку кредитной истории и скоринг на основе данных фермы", labelEn: "I consent to credit checks and scoring based on my farm data", required: true },
  },
  {
    value: "geo_data",
    label: "Sun'iy yo'ldosh, ob-havo va tuproq ma'lumotlarini yig'ishga roziman",
    metadata: { labelRu: "Согласен на сбор GEO-данных (спутник, погода, почва) для моих участков", labelEn: "I consent to satellite, weather, and soil data collection for my plots", required: true },
  },
  {
    value: "institution_sharing",
    label: "Ma'lumotlarim hamkor moliyaviy institutlar bilan baham ko'rilishiga roziman",
    metadata: {
      labelRu: "Согласен на передачу заявки партнёрским финансовым институтам",
      labelEn: "I consent to sharing my data with partner financial institutions",
      required: true,
    },
  },
  {
    value: "data_processing",
    label: "AGNET maxfiylik siyosatiga muvofiq ma'lumotlarim qayta ishlanishiga roziman",
    metadata: { labelRu: "Согласен на обработку данных согласно политике конфиденциальности AGNET", labelEn: "I consent to data processing under AGNET's privacy policy", required: true },
  },
];

const CROP_OPTIONS = [
  { value: "cotton", label: "Paxta", metadata: { labelRu: "Хлопок", labelEn: "Cotton" } },
  { value: "wheat", label: "Bug'doy", metadata: { labelRu: "Пшеница", labelEn: "Wheat" } },
  { value: "rice", label: "Sholi", metadata: { labelRu: "Рис", labelEn: "Rice" } },
  { value: "vegetables", label: "Sabzavotlar", metadata: { labelRu: "Овощи", labelEn: "Vegetables" } },
  { value: "fruits", label: "Mevalar", metadata: { labelRu: "Фрукты", labelEn: "Fruits" } },
];

const ASSET_TYPE_OPTIONS = [
  { value: "tractor", label: "Traktor", metadata: { labelRu: "Трактор", labelEn: "Tractor" } },
  { value: "harvester", label: "O'rish mashinasi", metadata: { labelRu: "Комбайн", labelEn: "Harvester" } },
  { value: "irrigation", label: "Sug'orish uskunalari", metadata: { labelRu: "Орошительное оборудование", labelEn: "Irrigation equipment" } },
  { value: "livestock", label: "Qoramol", metadata: { labelRu: "Скот", labelEn: "Livestock" } },
];

const FINANCE_PURPOSE_OPTIONS = [
  { value: "inputs", label: "Urug'lik va o'g'itlar", metadata: { labelRu: "Семена и удобрения", labelEn: "Seeds & fertilizers" } },
  { value: "equipment", label: "Uskunalar", metadata: { labelRu: "Оборудование", labelEn: "Equipment" } },
  { value: "working_capital", label: "Aylanma kapital", metadata: { labelRu: "Оборотный капитал", labelEn: "Working capital" } },
  { value: "land_improvement", label: "Yerni yaxshilash", metadata: { labelRu: "Улучшение земли", labelEn: "Land improvement" } },
];

const FINANCE_INSTITUTION_OPTIONS = [
  { value: "agrobank", label: "Agrobank", metadata: { labelRu: "Агробанк", labelEn: "Agrobank" } },
  { value: "ipoteka", label: "Ipoteka Bank", metadata: { labelRu: "Ипотека Банк", labelEn: "Ipoteka Bank" } },
];

const REQUIRED_DOC_OPTIONS = [
  { value: "national_id", label: "Milliy ID", metadata: { labelRu: "Национальный ID", labelEn: "National ID", optional: true } },
  { value: "land_deed", label: "Yer hujjati / e-Ijara", metadata: { labelRu: "Земельный документ / e-Ijara", labelEn: "Land deed / e-Ijara" } },
  { value: "bank_statement", label: "Bank ko'chirmasi (3 oy)", metadata: { labelRu: "Банковская выписка (3 мес.)", labelEn: "Bank statement (3 months)" } },
  { value: "tax_receipt", label: "Soliq kvitansiyasi", metadata: { labelRu: "Налоговая квитанция", labelEn: "Tax receipt", optional: true } },
  {
    value: "collateral_appraisal",
    label: "Garov baholash hisoboti",
    metadata: { labelRu: "Отчёт об оценке залога", labelEn: "Collateral appraisal report", institutions: ["agrobank"] },
  },
  {
    value: "income_certificate",
    label: "Daromad ma'lumotnomasi",
    metadata: { labelRu: "Справка о доходах", labelEn: "Income certificate", institutions: ["ipoteka"] },
  },
];

const INSTITUTION_OPTIONS = [
  {
    value: "inst-uz-agrobank-001",
    label: "Agrobank",
    metadata: { labelRu: "Агробанк", labelEn: "Agrobank", shortCode: "AGB" },
  },
  {
    value: "inst-uz-ipoteka-001",
    label: "Ipoteka Bank",
    metadata: { labelRu: "Ипотека банк", labelEn: "Ipoteka Bank", shortCode: "IPB" },
  },
  {
    value: "inst-uz-xalq-001",
    label: "Xalq Banki",
    metadata: { labelRu: "Халк банки", labelEn: "Xalq Bank", shortCode: "XBK" },
  },
];

/** Per-institution required document checklist (mirrors GET /institutions/{id}/checklist). */
const INSTITUTION_CHECKLISTS: Record<
  string,
  { docType: string; label: string; labelRu: string; required: boolean; maxSizeMb?: number }[]
> = {
  "inst-uz-agrobank-001": [
    { docType: "land_deed", label: "Yer hujjati", labelRu: "Земельный документ", required: true, maxSizeMb: 10 },
    { docType: "bank_statement", label: "Bank ko'chirmasi", labelRu: "Банковская выписка", required: true, maxSizeMb: 5 },
    { docType: "tax_receipt", label: "Soliq kvitansiyasi", labelRu: "Налоговая квитанция", required: false, maxSizeMb: 5 },
  ],
  "inst-uz-ipoteka-001": [
    { docType: "land_deed", label: "Yer hujjati", labelRu: "Земельный документ", required: true, maxSizeMb: 10 },
    { docType: "national_id", label: "Milliy ID", labelRu: "Национальный ID", required: true, maxSizeMb: 5 },
    { docType: "bank_statement", label: "Bank ko'chirmasi", labelRu: "Банковская выписка", required: true, maxSizeMb: 5 },
  ],
  "inst-uz-xalq-001": [
    { docType: "land_deed", label: "Yer hujjati", labelRu: "Земельный документ", required: true, maxSizeMb: 10 },
    { docType: "bank_statement", label: "Bank ko'chirmasi", labelRu: "Банковская выписка", required: true, maxSizeMb: 5 },
  ],
};

function localizeOption(
  option: { value: string; label: string; metadata?: Record<string, unknown> },
  locale?: string,
) {
  if (locale === "ru" && typeof option.metadata?.labelRu === "string") {
    return { value: option.value, label: option.metadata.labelRu, metadata: option.metadata };
  }
  if (locale === "en" && typeof option.metadata?.labelEn === "string") {
    return { value: option.value, label: option.metadata.labelEn, metadata: option.metadata };
  }
  return { value: option.value, label: option.label, metadata: option.metadata };
}

export function handleDevReferenceOptions(searchParams: URLSearchParams): {
  status: number;
  data: unknown;
} {
  const type = searchParams.get("type") ?? "";
  const region = searchParams.get("region");
  const locale = searchParams.get("locale") ?? undefined;

  switch (type) {
    case "regions":
      return {
        status: 200,
        data: UZ_REGIONS.map((r) =>
          localizeOption(
            { value: r.value, label: r.labelUz, metadata: { labelRu: r.labelRu } },
            locale,
          ),
        ),
      };
    case "districts": {
      const districts = region
        ? UZ_REGIONS.find((r) => r.value === region)?.districts ?? []
        : UZ_REGIONS.flatMap((r) => r.districts);
      return {
        status: 200,
        data: districts.map((d) =>
          localizeOption(
            {
              value: d.value,
              label: d.labelUz,
              metadata: { labelRu: d.labelRu, region: findRegionForDistrictValue(d.value) },
            },
            locale,
          ),
        ),
      };
    }
    case "consent_types":
      return { status: 200, data: CONSENT_TYPE_OPTIONS.map((o) => localizeOption(o, locale)) };
    case "crops":
      return { status: 200, data: CROP_OPTIONS.map((o) => localizeOption(o, locale)) };
    case "asset_types":
      return { status: 200, data: ASSET_TYPE_OPTIONS.map((o) => localizeOption(o, locale)) };
    case "finance_purposes":
      return { status: 200, data: FINANCE_PURPOSE_OPTIONS.map((o) => localizeOption(o, locale)) };
    case "finance_institutions":
      return { status: 200, data: FINANCE_INSTITUTION_OPTIONS.map((o) => localizeOption(o, locale)) };
    case "required_docs":
      return { status: 200, data: REQUIRED_DOC_OPTIONS.map((o) => localizeOption(o, locale)) };
    case "institutions":
      return { status: 200, data: INSTITUTION_OPTIONS.map((o) => localizeOption(o, locale)) };
    case "institution_checklist": {
      const institutionId = searchParams.get("institutionId");
      if (!institutionId) {
        return { status: 400, data: { message: "institutionId is required for institution_checklist" } };
      }
      const items = INSTITUTION_CHECKLISTS[institutionId];
      if (!items) {
        return { status: 404, data: { message: `Unknown institution: ${institutionId}` } };
      }
      return {
        status: 200,
        data: items.map((item) =>
          localizeOption(
            {
              value: item.docType,
              label: item.label,
              metadata: {
                labelRu: item.labelRu,
                docType: item.docType,
                required: item.required,
                maxSizeMb: item.maxSizeMb,
                institutionId,
              },
            },
            locale,
          ),
        ),
      };
    }
    default:
      return { status: 400, data: { message: `Unknown reference type: ${type}` } };
  }
}

function findRegionForDistrictValue(districtValue: string): string | undefined {
  return UZ_REGIONS.find((r) => r.districts.some((d) => d.value === districtValue))?.value;
}

export function handleDevCountryConfig(code: string): { status: number; data: unknown } {
  if (code.toUpperCase() !== "UZ") {
    return { status: 404, data: { message: `Country ${code} not found` } };
  }
  return {
    status: 200,
    data: {
      countryCode: "UZ",
      languages: ["uz", "ru", "en"],
      consentVersion: "2026.1",
      featureFlags: {
        ENABLE_ML_SCORING: false,
        ENABLE_OCR: true,
        UZ_LAND_REGISTRY_LIVE: false,
      },
      appearance: {
        allowedThemes: ["light", "dark", "system"],
        defaultTheme: "system",
        darkModeEnabled: true,
      },
    },
  };
}

const farmerPreferences = new Map<string, string>();

export function handleDevFarmerPreferences(
  userId: string,
  body: { primaryLanguage?: string },
): { status: number; data: unknown } {
  const allowed = ["uz", "ru", "en"];
  const lang = body?.primaryLanguage;
  if (!lang || !allowed.includes(lang)) {
    return {
      status: 400,
      data: { message: `Invalid language. Allowed: ${allowed.join(", ")}` },
    };
  }
  farmerPreferences.set(userId, lang);
  return { status: 200, data: { primaryLanguage: lang } };
}

export function getDevSession(sessionId: string): MockSession | undefined {
  return sessions.get(sessionId);
}

export function getDevUser(userId: string): MockUser | undefined {
  return users.get(userId);
}

export function listDevSessionIds(): string[] {
  return Array.from(sessions.keys());
}
