"use server";

import { getAdminUser } from "@/lib/admin-permissions";
import { pool } from "@/lib/db";
import { uploadObject, BUCKETS } from "@/lib/storage";

export type UploadLogoResult =
  | { success: true; logoUrl: string }
  | { success: false; error: string };

/**
 * Upload a brand logo (light or dark variant) to MinIO and save the
 * resulting public URL to the brand_settings row via the
 * `upsert_brand_settings` SECURITY DEFINER RPC.
 */
export async function uploadBrandLogo(
  brandId: string,
  file: File,
  isDark: boolean = false
): Promise<UploadLogoResult> {
  const adminUser = await getAdminUser();
  if (!adminUser) return { success: false, error: "Not authenticated" };
  if (!adminUser.can_manage_settings && adminUser.role !== "platform_admin") {
    return { success: false, error: "Not authorized" };
  }
  if (adminUser.role === "brand_admin" && adminUser.brand_id !== brandId) {
    return { success: false, error: "Not authorized for this brand" };
  }

  const validTypes = ["image/png", "image/jpeg", "image/webp", "image/svg+xml"];
  if (!validTypes.includes(file.type)) {
    return { success: false, error: "Invalid file type. Use PNG, JPEG, WebP, or SVG." };
  }
  if (file.size > 5 * 1024 * 1024) {
    return { success: false, error: "File too large. Max 5MB." };
  }

  const ext = file.type === "image/svg+xml" ? "svg" : file.type.split("/")[1];
  const path = isDark ? `logo-dark.${ext}` : `logo.${ext}`;
  const storageKey = `brand-logos/${brandId}/${path}`;

  try {
    const buffer = Buffer.from(await file.arrayBuffer());
    const logoUrl = await uploadObject({
      bucket: BUCKETS.BRAND_LOGOS,
      key: storageKey,
      body: buffer,
      contentType: file.type,
    });

    const saveOk = await callUpsertBrandSettings(brandId, {
      [isDark ? "p_logo_url_dark" : "p_logo_url"]: logoUrl,
    });
    if (!saveOk) {
      return { success: false, error: "Upload succeeded but failed to save URL" };
    }

    return { success: true, logoUrl };
  } catch (err) {
    return { success: false, error: `Upload failed: ${err instanceof Error ? err.message : String(err)}` };
  }
}

export async function uploadOlatheSweetLogo(
  brandId: string,
  file: File
): Promise<UploadLogoResult> {
  const adminUser = await getAdminUser();
  if (!adminUser) return { success: false, error: "Not authenticated" };
  if (!adminUser.can_manage_settings && adminUser.role !== "platform_admin") {
    return { success: false, error: "Not authorized" };
  }
  if (adminUser.role === "brand_admin" && adminUser.brand_id !== brandId) {
    return { success: false, error: "Not authorized for this brand" };
  }

  const validTypes = ["image/png", "image/jpeg", "image/webp", "image/svg+xml"];
  if (!validTypes.includes(file.type)) {
    return { success: false, error: "Invalid file type. Use PNG, JPEG, WebP, or SVG." };
  }
  if (file.size > 5 * 1024 * 1024) {
    return { success: false, error: "File too large. Max 5MB." };
  }

  const ext = file.type === "image/svg+xml" ? "svg" : file.type.split("/")[1];
  const storageKey = `brand-logos/${brandId}/olathe-sweet-logo.${ext}`;

  try {
    const buffer = Buffer.from(await file.arrayBuffer());
    const logoUrl = await uploadObject({
      bucket: BUCKETS.BRAND_LOGOS,
      key: storageKey,
      body: buffer,
      contentType: file.type,
    });

    const saveOk = await callUpsertBrandSettings(brandId, {
      p_olathe_sweet_logo_url: logoUrl,
    });
    if (!saveOk) {
      return { success: false, error: "Upload succeeded but failed to save URL" };
    }

    return { success: true, logoUrl };
  } catch (err) {
    return { success: false, error: `Upload failed: ${err instanceof Error ? err.message : String(err)}` };
  }
}

export async function uploadOlatheSweetLogoDark(
  brandId: string,
  file: File
): Promise<UploadLogoResult> {
  const adminUser = await getAdminUser();
  if (!adminUser) return { success: false, error: "Not authenticated" };
  if (!adminUser.can_manage_settings && adminUser.role !== "platform_admin") {
    return { success: false, error: "Not authorized" };
  }
  if (adminUser.role === "brand_admin" && adminUser.brand_id !== brandId) {
    return { success: false, error: "Not authorized for this brand" };
  }

  const validTypes = ["image/png", "image/jpeg", "image/webp", "image/svg+xml"];
  if (!validTypes.includes(file.type)) {
    return { success: false, error: "Invalid file type. Use PNG, JPEG, WebP, or SVG." };
  }
  if (file.size > 5 * 1024 * 1024) {
    return { success: false, error: "File too large. Max 5MB." };
  }

  const ext = file.type === "image/svg+xml" ? "svg" : file.type.split("/")[1];
  const storageKey = `brand-logos/${brandId}/olathe-sweet-logo-dark.${ext}`;

  try {
    const buffer = Buffer.from(await file.arrayBuffer());
    const logoUrl = await uploadObject({
      bucket: BUCKETS.BRAND_LOGOS,
      key: storageKey,
      body: buffer,
      contentType: file.type,
    });

    const saveOk = await callUpsertBrandSettings(brandId, {
      p_olathe_sweet_logo_url_dark: logoUrl,
    });
    if (!saveOk) {
      return { success: false, error: "Upload succeeded but failed to save URL" };
    }

    return { success: true, logoUrl };
  } catch (err) {
    return { success: false, error: `Upload failed: ${err instanceof Error ? err.message : String(err)}` };
  }
}

/**
 * Internal helper: invoke the SECURITY DEFINER `upsert_brand_settings`
 * RPC via the shared pg pool. Accepts a partial args object whose keys
 * map to the function's `p_*` parameters.
 */
async function callUpsertBrandSettings(
  brandId: string,
  args: Record<string, unknown>
): Promise<boolean> {
  // Always set the brand id.
  args.p_brand_id = brandId;

  // Build a `$1, $2, ...` parameter list in deterministic key order so
  // the positional binds line up with the named parameters.
  const keys = Object.keys(args);
  const placeholders = keys.map((_, i) => `$${i + 1}`).join(", ");
  const params = keys.map((k) => args[k]);

  try {
    await pool.query(
      `SELECT upsert_brand_settings(${placeholders})`,
      params,
    );
    return true;
  } catch {
    return false;
  }
}

export type BrandSettings = {
  id?: string;
  brand_id: string;
  brand_name: string;
  legal_business_name: string | null;
  phone: string | null;
  email: string | null;
  website_url: string | null;
  street_address: string | null;
  city: string | null;
  state: string | null;
  postal_code: string | null;
  country: string | null;
  logo_url: string | null;
  logo_url_dark: string | null;
  olathe_sweet_logo_url: string | null;
  olathe_sweet_logo_url_dark: string | null;
  default_email_signature: string | null;
  invoice_footer_notes: string | null;
  // Storefront customization fields
  hero_tagline: string | null;
  about_headline: string | null;
  about_subheadline: string | null;
  custom_footer_text: string | null;
  show_wholesale_link: boolean | null;
  show_zip_search: boolean | null;
  show_schedule_pdf: boolean | null;
  show_text_alerts: boolean | null;
  schedule_pdf_notes: string | null;
  hero_image_url: string | null;
  // Color customization
  brand_primary_color: string | null;
  brand_secondary_color: string | null;
  brand_bg_color: string | null;
  brand_text_color: string | null;
  // Tax settings
  collect_sales_tax: boolean | null;
  nexus_states: string[] | null;
  updated_at?: string;
};

export type GetBrandSettingsResult =
  | { success: true; settings: BrandSettings | null }
  | { success: false; error: string };

export type SaveBrandSettingsResult =
  | { success: true; settings: BrandSettings }
  | { success: false; error: string };

export async function getBrandSettings(brandId: string): Promise<GetBrandSettingsResult> {
  try {
    const { rows } = await pool.query<BrandSettings>(
      "SELECT * FROM get_brand_settings($1)",
      [brandId],
    );
    return { success: true, settings: rows[0] ?? null };
  } catch {
    return { success: false, error: "Failed to fetch brand settings" };
  }
}

// Public version for storefront pages — uses slug, no auth required
export async function getBrandSettingsPublic(brandSlug: string): Promise<GetBrandSettingsResult & { wholesaleEnabled?: boolean | null }> {
  // Wrapped in try/catch so a build-time DB outage (ECONNREFUSED) doesn't
  // crash the prerender — the page just falls back to its default brand
  // name and revalidates from a real request later.
  try {
    const { rows } = await pool.query<BrandSettings & { wholesale_enabled?: boolean | null }>(
      "SELECT * FROM get_brand_settings_by_slug($1)",
      [brandSlug],
    );
    const data = rows[0];
    if (!data) {
      return { success: false, error: "Failed to fetch brand settings", wholesaleEnabled: undefined };
    }
    return {
      success: true,
      settings: data,
      wholesaleEnabled: data.wholesale_enabled,
    };
  } catch {
    return { success: false, error: "Failed to fetch brand settings", wholesaleEnabled: undefined };
  }
}

export async function saveBrandSettings(params: {
  brandId: string;
  legalBusinessName?: string;
  phone?: string;
  email?: string;
  websiteUrl?: string;
  streetAddress?: string;
  city?: string;
  state?: string;
  postalCode?: string;
  country?: string;
  logoUrl?: string;
  logoUrlDark?: string;
  olatheSweetLogoUrl?: string;
  olatheSweetLogoUrlDark?: string;
  defaultEmailSignature?: string;
  invoiceFooterNotes?: string;
  // Storefront customization fields
  heroTagline?: string;
  aboutHeadline?: string;
  aboutSubheadline?: string;
  customFooterText?: string;
  showWholesaleLink?: boolean;
  showZipSearch?: boolean;
  showSchedulePdf?: boolean;
  showTextAlerts?: boolean;
  schedulePdfNotes?: string;
  heroImageUrl?: string;
  brandPrimaryColor?: string;
  brandSecondaryColor?: string;
  brandBgColor?: string;
  brandTextColor?: string;
  collectSalesTax?: boolean;
  nexusStates?: string[];
}): Promise<SaveBrandSettingsResult> {
  const adminUser = await getAdminUser();
  if (!adminUser) return { success: false, error: "Not authenticated" };
  if (!adminUser.can_manage_settings && adminUser.role !== "platform_admin") {
    return { success: false, error: "Not authorized" };
  }

  if (adminUser.role === "brand_admin" && adminUser.brand_id !== params.brandId) {
    return { success: false, error: "Not authorized for this brand" };
  }

  try {
    const { rows } = await pool.query<BrandSettings>(
      `SELECT * FROM upsert_brand_settings(
         $1, $2, $3, $4, $5, $6, $7, $8, $9, $10,
         $11, $12, $13, $14, $15, $16, $17, $18, $19, $20,
         $21, $22, $23, $24, $25, $26, $27, $28, $29, $30,
         $31, $32
       )`,
      [
        params.brandId,
        params.legalBusinessName ?? null,
        params.phone ?? null,
        params.email ?? null,
        params.websiteUrl ?? null,
        params.streetAddress ?? null,
        params.city ?? null,
        params.state ?? null,
        params.postalCode ?? null,
        params.country ?? null,
        params.logoUrl ?? null,
        params.logoUrlDark ?? null,
        params.olatheSweetLogoUrl ?? null,
        params.olatheSweetLogoUrlDark ?? null,
        params.defaultEmailSignature ?? null,
        params.invoiceFooterNotes ?? null,
        params.heroTagline ?? null,
        params.aboutHeadline ?? null,
        params.aboutSubheadline ?? null,
        params.customFooterText ?? null,
        params.showWholesaleLink ?? null,
        params.showZipSearch ?? null,
        params.showSchedulePdf ?? null,
        params.showTextAlerts ?? null,
        params.schedulePdfNotes ?? null,
        params.heroImageUrl ?? null,
        params.brandPrimaryColor ?? null,
        params.brandSecondaryColor ?? null,
        params.brandBgColor ?? null,
        params.brandTextColor ?? null,
        params.collectSalesTax ?? null,
        params.nexusStates ?? null,
      ],
    );
    return { success: true, settings: rows[0] as BrandSettings };
  } catch (err) {
    const message = err instanceof Error ? err.message : "Failed to save";
    return { success: false, error: `Failed to save: ${message.slice(0, 200)}` };
  }
}
