import type { AppSetting } from "@prisma/client";

import { normalizeLocale, type AppLocale } from "@/lib/i18n";
import { prisma } from "@/lib/prisma";
import type { AppSettings } from "@/types/settings";

const SETTINGS_SINGLETON_KEY = "SYSTEM";

function getEnvString(name: string, fallback = "") {
  return process.env[name]?.trim() ?? fallback;
}

function getEnvNumber(name: string, fallback: number) {
  const value = Number(process.env[name] ?? fallback);
  return Number.isFinite(value) ? value : fallback;
}

function getEnvBoolean(name: string, fallback: boolean) {
  const value = process.env[name];
  if (!value) return fallback;
  return value === "true" || value === "1";
}

export function getAppSettingsDefaults(): AppSettings {
  return {
    company_name: "AbelBirdnest Stock",
    company_email: "",
    company_phone: "",
    company_bank_name: "",
    company_bank_account_number: "",
    company_bank_accounts: [],
    company_address: "",
    company_timezone: "Asia/Jakarta",
    smtp_host: getEnvString("SMTP_HOST"),
    smtp_port: getEnvNumber("SMTP_PORT", 465),
    smtp_secure: getEnvBoolean("SMTP_SECURE", getEnvNumber("SMTP_PORT", 465) === 465),
    smtp_user: getEnvString("SMTP_USER"),
    smtp_password: "",
    smtp_from_name: "AbelBirdnest Stock",
    smtp_from_email: getEnvString("SMTP_FROM", getEnvString("SMTP_USER")),
    purchase_prefix: "PO",
    receipt_prefix: "RCV",
    lot_prefix: "LOT",
    adjustment_prefix: "STA",
    transformation_prefix: "MIX",
    fund_request_prefix: "FR",
    washing_prefix: "WSH",
    regular_sale_prefix: "SRG",
    jit_sale_prefix: "SJT",
    consignment_prefix: "TJT",
    default_locale: "id",
    currency_code: "IDR",
    date_format: "DD/MM/YYYY",
    password_min_length: 8,
    session_timeout_minutes: 720,
    require_email_verification: true,
    audit_retention_days: 365,
    updated_at: null
  };
}

type AppSettingsRecord =
  | (AppSetting & {
      companyBankAccounts?: Array<{
        bankId: bigint;
        accountNumber: string;
        bank: {
          code: string;
          name: string;
        };
      }>;
    })
  | null;

export function serializeAppSettings(record: AppSettingsRecord): AppSettings {
  const defaults = getAppSettingsDefaults();
  const companyBankAccounts = record?.companyBankAccounts ?? [];
  const primaryCompanyBankAccount = companyBankAccounts[0] ?? null;

  return {
    company_name: record?.companyName ?? defaults.company_name,
    company_email: record?.companyEmail ?? defaults.company_email,
    company_phone: record?.companyPhone ?? defaults.company_phone,
    company_bank_name:
      primaryCompanyBankAccount?.bank.name ??
      record?.companyBankName ??
      defaults.company_bank_name,
    company_bank_account_number:
      primaryCompanyBankAccount?.accountNumber ??
      record?.companyBankAccountNumber ??
      defaults.company_bank_account_number,
    company_bank_accounts: companyBankAccounts.map((account) => ({
      bank_id: account.bankId.toString(),
      bank_code: account.bank.code,
      bank_name: account.bank.name,
      account_number: account.accountNumber
    })),
    company_address: record?.companyAddress ?? defaults.company_address,
    company_timezone: record?.companyTimezone ?? defaults.company_timezone,
    smtp_host: record?.smtpHost ?? defaults.smtp_host,
    smtp_port: record?.smtpPort ?? defaults.smtp_port,
    smtp_secure: record?.smtpSecure ?? defaults.smtp_secure,
    smtp_user: record?.smtpUser ?? defaults.smtp_user,
    smtp_password: "",
    smtp_from_name: record?.smtpFromName ?? defaults.smtp_from_name,
    smtp_from_email: record?.smtpFromEmail ?? defaults.smtp_from_email,
    purchase_prefix: record?.purchasePrefix ?? defaults.purchase_prefix,
    receipt_prefix: record?.receiptPrefix ?? defaults.receipt_prefix,
    lot_prefix: record?.lotPrefix ?? defaults.lot_prefix,
    adjustment_prefix: record?.adjustmentPrefix ?? defaults.adjustment_prefix,
    transformation_prefix: record?.transformationPrefix ?? defaults.transformation_prefix,
    fund_request_prefix: record?.fundRequestPrefix ?? defaults.fund_request_prefix,
    washing_prefix: record?.washingPrefix ?? defaults.washing_prefix,
    regular_sale_prefix: record?.regularSalePrefix ?? defaults.regular_sale_prefix,
    jit_sale_prefix: record?.jitSalePrefix ?? defaults.jit_sale_prefix,
    consignment_prefix: record?.consignmentPrefix ?? defaults.consignment_prefix,
    default_locale: normalizeLocale(record?.defaultLocale) as "id" | "en",
    currency_code: record?.currencyCode ?? defaults.currency_code,
    date_format: record?.dateFormat ?? defaults.date_format,
    password_min_length: record?.passwordMinLength ?? defaults.password_min_length,
    session_timeout_minutes: record?.sessionTimeoutMinutes ?? defaults.session_timeout_minutes,
    require_email_verification:
      record?.requireEmailVerification ?? defaults.require_email_verification,
    audit_retention_days: record?.auditRetentionDays ?? defaults.audit_retention_days,
    updated_at: record?.updatedAt.toISOString() ?? null
  };
}

export async function getAppSettingsRecord() {
  return prisma.appSetting.findUnique({
    where: { singletonKey: SETTINGS_SINGLETON_KEY },
    include: {
      companyBankAccounts: {
        include: {
          bank: true
        },
        orderBy: [{ createdAt: "asc" }, { id: "asc" }]
      }
    }
  });
}

export async function getAppSettings() {
  const record = await getAppSettingsRecord();
  return serializeAppSettings(record);
}

export async function getDefaultAppLocale(): Promise<AppLocale> {
  try {
    const settings = await getAppSettings();
    return normalizeLocale(settings.default_locale);
  } catch {
    return "id";
  }
}

export async function getSessionTimeoutSeconds() {
  try {
    const settings = await getAppSettings();
    return settings.session_timeout_minutes * 60;
  } catch {
    return 60 * 60 * 12;
  }
}

export async function isEmailVerificationRequired() {
  try {
    const settings = await getAppSettings();
    return settings.require_email_verification;
  } catch {
    return true;
  }
}

export async function getSmtpRuntimeConfig() {
  const record = await getAppSettingsRecord();
  const defaults = getAppSettingsDefaults();

  const host = record?.smtpHost ?? defaults.smtp_host;
  const port = record?.smtpPort ?? defaults.smtp_port;
  const secure = record?.smtpSecure ?? defaults.smtp_secure;
  const user = record?.smtpUser ?? defaults.smtp_user;
  const pass = record?.smtpPassword ?? process.env.SMTP_PASSWORD ?? "";
  const fromName = record?.smtpFromName ?? defaults.smtp_from_name;
  const fromEmail = record?.smtpFromEmail ?? defaults.smtp_from_email;

  return {
    host,
    port,
    secure,
    user,
    pass,
    fromName,
    fromEmail
  };
}
