"use client";

import { Skeleton } from "@/components/atoms";
import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner";
import { Button } from "@/components/atoms/button";
import { SubCard } from "@/components/molecules/SubCard/SubCard";

import { useState, useEffect, useCallback, useRef } from "react";
import { useQueryClient } from "@tanstack/react-query";
import { accountService } from "@/features/account/api/account.api";
import { logger } from "@/core/logger";
import { StatusPill } from "@/components/atoms/status-pill";
import { MapPinIcon, PencilIcon, CheckIcon, XMarkIcon } from "@heroicons/react/24/outline";
import { getCountryName } from "@/shared/constants";
import { queryKeys } from "@/core/api";

// Use canonical Address type from domain
import type { Address } from "@customer-portal/domain/customer";
import type { BilingualAddress } from "@customer-portal/domain/address";
import { ORDER_TYPE } from "@customer-portal/domain/orders";

// Japan address form with ZIP lookup
import { JapanAddressForm } from "@/features/address/components/JapanAddressForm";

interface BillingInfo {
  company: string | null;
  email: string;
  phone: string | null;
  address: Address | null;
  isComplete: boolean;
}

function isAddressDataComplete(address: Address | null): boolean {
  return !!(
    address &&
    address.address1 &&
    address.city &&
    address.state &&
    address.postcode &&
    address.country
  );
}

function buildBillingInfo(address: Address | null): BillingInfo {
  return {
    company: null,
    email: "",
    phone: null,
    address,
    isComplete: isAddressDataComplete(address),
  };
}

function normalizeAddress(data: Address | null): Address | null {
  if (!data) return null;
  return {
    ...data,
    country: data.country ?? "",
    countryCode: data.countryCode ?? data.country ?? "",
  };
}

function getCountryLabel(address: Address | null): string | null {
  if (!address?.country) return null;
  return getCountryName(address.country) ?? address.country;
}

function getHeaderTitle(
  titleOverride?: string,
  isInternetOrder?: boolean,
  isComplete?: boolean
): string {
  if (titleOverride) return titleOverride;
  if (isInternetOrder) return "Installation Address";
  if (isComplete) return "Service Address";
  return "Complete Your Address";
}

function AddressConfirmationHeader({
  headerTitle,
  statusVariant,
  showConfirmAction,
  showEditAction,
  onConfirm,
  onEdit,
}: {
  headerTitle: string;
  statusVariant: "success" | "warning";
  showConfirmAction: boolean;
  showEditAction: boolean;
  onConfirm: (e: React.MouseEvent<HTMLButtonElement>) => void;
  onEdit: (e?: React.MouseEvent<HTMLButtonElement>) => void;
}) {
  return (
    <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between mb-4">
      <div className="flex items-center space-x-3">
        <MapPinIcon className="h-5 w-5 text-primary" />
        <div>
          <h3 className="text-lg font-semibold text-foreground">{headerTitle}</h3>
        </div>
      </div>
      <div className="flex flex-wrap items-center gap-2 sm:justify-end">
        <StatusPill
          label={statusVariant === "success" ? "Verified" : "Pending confirmation"}
          variant={statusVariant}
        />
        {showConfirmAction ? (
          <Button
            type="button"
            size="sm"
            onClick={onConfirm}
            onKeyDown={e => {
              if (e.key === "Enter" || e.key === " ") {
                e.preventDefault();
                e.stopPropagation();
              }
            }}
          >
            Confirm Address
          </Button>
        ) : null}
        {showEditAction ? (
          <Button
            type="button"
            variant="outline"
            size="sm"
            onClick={onEdit}
            leftIcon={<PencilIcon className="h-4 w-4" />}
          >
            Edit Address
          </Button>
        ) : null}
      </div>
    </div>
  );
}

function AddressEditForm({
  onAddressChange,
  onSave,
  onCancel,
  isSaving,
  isComplete,
  error,
}: {
  onAddressChange: (address: BilingualAddress, complete: boolean) => void;
  onSave: (e: React.MouseEvent<HTMLButtonElement>) => void;
  onCancel: (e: React.MouseEvent<HTMLButtonElement>) => void;
  isSaving: boolean;
  isComplete: boolean;
  error: string | null;
}) {
  return (
    <div className="space-y-4">
      <AlertBanner variant="info" title="Japan Address" size="sm">
        Enter your ZIP code to auto-fill address fields from Japan Post.
      </AlertBanner>

      <JapanAddressForm onChange={onAddressChange} disabled={isSaving} />

      {error && (
        <AlertBanner variant="error" title="Error" size="sm">
          {error}
        </AlertBanner>
      )}

      <div className="flex items-center space-x-3 pt-4">
        <Button
          type="button"
          onClick={onSave}
          leftIcon={<CheckIcon className="h-4 w-4" />}
          disabled={!isComplete || isSaving}
          isLoading={isSaving}
          loadingText="Saving..."
        >
          Save Address
        </Button>
        <Button
          type="button"
          onClick={onCancel}
          variant="outline"
          leftIcon={<XMarkIcon className="h-4 w-4" />}
          disabled={isSaving}
        >
          Cancel
        </Button>
      </div>
    </div>
  );
}

function AddressDisplay({
  address,
  countryLabel,
  isInternetOrder,
  addressConfirmed,
  confirmationMessage,
  onEdit,
}: {
  address: Address | null;
  countryLabel: string | null;
  isInternetOrder: boolean;
  addressConfirmed: boolean;
  confirmationMessage: string;
  onEdit: () => void;
}) {
  if (!address?.address1) {
    return (
      <div className="text-center py-8">
        <div className="w-16 h-16 bg-muted rounded-full flex items-center justify-center mx-auto mb-4 border border-border shadow-[var(--cp-shadow-1)]">
          <MapPinIcon className="h-8 w-8 text-muted-foreground" />
        </div>
        <h4 className="text-lg font-medium text-foreground mb-2">No Address on File</h4>
        <p className="text-muted-foreground mb-6">
          Please add your installation address to continue.
        </p>
        <Button type="button" onClick={onEdit}>
          Add Address
        </Button>
      </div>
    );
  }

  return (
    <div className="space-y-4">
      <div className="text-foreground space-y-1">
        {(address.address2 || address.address1) && (
          <p className="font-semibold text-base">{address.address2 || address.address1}</p>
        )}
        {address.address2 && address.address1 ? (
          <p className="text-muted-foreground">{address.address1}</p>
        ) : null}
        <p className="text-muted-foreground">
          {[address.city, address.state].filter(Boolean).join(", ")}
          {address.postcode ? ` ${address.postcode}` : ""}
        </p>
        {countryLabel && <p className="text-muted-foreground">{countryLabel}</p>}
      </div>

      {isInternetOrder && !addressConfirmed && (
        <AlertBanner variant="warning" title="Verification Required" size="sm" elevated>
          {confirmationMessage}
        </AlertBanner>
      )}
    </div>
  );
}

interface SaveAddressContext {
  queryClient: ReturnType<typeof useQueryClient>;
  setBillingInfo: (info: BillingInfo) => void;
  onAddressConfirmed: (address: Address) => void;
  setEditing: (v: boolean) => void;
  setAddressConfirmed: (v: boolean) => void;
  setIsSaving: (v: boolean) => void;
  setError: (e: string | null) => void;
}

async function saveAddress(bilingualAddress: BilingualAddress, ctx: SaveAddressContext) {
  try {
    ctx.setError(null);
    ctx.setIsSaving(true);
    const updatedAddress = await accountService.updateBilingualAddress(bilingualAddress);
    await ctx.queryClient.invalidateQueries({ queryKey: queryKeys.services.all() });
    ctx.setBillingInfo(buildBillingInfo(updatedAddress));
    ctx.onAddressConfirmed(updatedAddress);
    ctx.setEditing(false);
    ctx.setAddressConfirmed(true);
    logger.info("Address updated with dual-write (WHMCS + Salesforce)", {
      hasJapaneseAddress: !!bilingualAddress.prefectureJa,
    });
  } catch (err) {
    ctx.setError(err instanceof Error ? err.message : "Failed to update address");
  } finally {
    ctx.setIsSaving(false);
  }
}

function useAddressConfirmationState(
  onAddressConfirmed: (address?: Address) => void,
  onAddressIncomplete: () => void,
  requiresAddressVerification: boolean
) {
  const queryClient = useQueryClient();
  const [billingInfo, setBillingInfo] = useState<BillingInfo | null>(null);
  const [loading, setLoading] = useState(true);
  const [editing, setEditing] = useState(false);
  const [bilingualAddress, setBilingualAddress] = useState<Partial<BilingualAddress> | null>(null);
  const [isAddressComplete, setIsAddressComplete] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [addressConfirmed, setAddressConfirmed] = useState(false);
  const [isSaving, setIsSaving] = useState(false);
  const onAddressConfirmedRef = useRef(onAddressConfirmed);
  const onAddressIncompleteRef = useRef(onAddressIncomplete);

  useEffect(() => {
    onAddressConfirmedRef.current = onAddressConfirmed;
  }, [onAddressConfirmed]);
  useEffect(() => {
    onAddressIncompleteRef.current = onAddressIncomplete;
  }, [onAddressIncomplete]);

  const fetchBillingInfo = useCallback(async () => {
    try {
      setLoading(true);
      const normalizedAddr = normalizeAddress(await accountService.getAddress());
      const info = buildBillingInfo(normalizedAddr);
      setBillingInfo(info);

      if (requiresAddressVerification) {
        setAddressConfirmed(false);
        onAddressIncompleteRef.current();
      } else if (info.isComplete && normalizedAddr) {
        onAddressConfirmedRef.current(normalizedAddr);
        setAddressConfirmed(true);
      } else {
        onAddressIncompleteRef.current();
        setAddressConfirmed(false);
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to load address");
    } finally {
      setLoading(false);
    }
  }, [requiresAddressVerification]);

  useEffect(() => {
    logger.info("Address confirmation component mounted");
    void fetchBillingInfo();
  }, [fetchBillingInfo]);

  const handleEdit = (e?: React.MouseEvent<HTMLButtonElement>) => {
    e?.preventDefault();
    e?.stopPropagation();
    setEditing(true);
    setError(null);
    setBilingualAddress(null);
    setIsAddressComplete(false);
  };

  const handleBilingualAddressChange = useCallback(
    (address: BilingualAddress, complete: boolean) => {
      setBilingualAddress(address);
      setIsAddressComplete(complete);
      setError(null);
    },
    []
  );

  const handleSave = useCallback(
    (e: React.MouseEvent<HTMLButtonElement>) => {
      e.preventDefault();
      e.stopPropagation();
      if (!bilingualAddress || !isAddressComplete) {
        setError("Please complete all required address fields");
        return;
      }
      void saveAddress(bilingualAddress as BilingualAddress, {
        queryClient,
        setBillingInfo,
        onAddressConfirmed,
        setEditing,
        setAddressConfirmed,
        setIsSaving,
        setError,
      });
    },
    [bilingualAddress, isAddressComplete, queryClient, onAddressConfirmed]
  );

  const handleConfirmAddress = useCallback(
    (e: React.MouseEvent<HTMLButtonElement>) => {
      e.preventDefault();
      e.stopPropagation();
      logger.info("Confirm installation address clicked");
      if (billingInfo?.address) {
        onAddressConfirmed(billingInfo.address);
        setAddressConfirmed(true);
      } else {
        setAddressConfirmed(false);
      }
    },
    [billingInfo, onAddressConfirmed]
  );

  const handleCancel = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
    e.preventDefault();
    e.stopPropagation();
    setEditing(false);
    setBilingualAddress(null);
    setIsAddressComplete(false);
    setError(null);
  }, []);

  return {
    billingInfo,
    loading,
    editing,
    isAddressComplete,
    error,
    addressConfirmed,
    isSaving,
    fetchBillingInfo,
    handleEdit,
    handleBilingualAddressChange,
    handleSave,
    handleConfirmAddress,
    handleCancel,
  };
}

interface AddressConfirmationProps {
  onAddressConfirmed: (address?: Address) => void;
  onAddressIncomplete: () => void;
  orderType?: string;
  embedded?: boolean;
  titleOverride?: string;
  confirmationPrompt?: string;
}

const DEFAULT_CONFIRMATION_PROMPT =
  "Please confirm this is the correct installation address for your internet service.";

function AddressConfirmationContent({
  isInternetOrder,
  titleOverride,
  confirmationPrompt,
  state,
}: {
  isInternetOrder: boolean;
  titleOverride: string | undefined;
  confirmationPrompt: string | undefined;
  state: ReturnType<typeof useAddressConfirmationState>;
}) {
  const {
    billingInfo,
    loading,
    editing,
    isAddressComplete,
    error,
    addressConfirmed,
    isSaving,
    fetchBillingInfo,
    handleEdit,
    handleBilingualAddressChange,
    handleSave,
    handleConfirmAddress,
    handleCancel,
  } = state;

  if (loading) {
    return (
      <div className="flex items-center space-x-3">
        <Skeleton className="h-4 w-4 rounded-full" />
        <span className="text-muted-foreground">Loading address information...</span>
      </div>
    );
  }

  if (error && !billingInfo) {
    return (
      <AlertBanner variant="error" title="Address Error" elevated>
        <div className="flex items-center justify-between">
          <span>{error}</span>
          <Button type="button" size="sm" variant="outline" onClick={() => void fetchBillingInfo()}>
            Try Again
          </Button>
        </div>
      </AlertBanner>
    );
  }

  if (!billingInfo) return null;

  const { address } = billingInfo;
  const countryLabel = getCountryLabel(address);
  const statusVariant: "success" | "warning" =
    addressConfirmed || !isInternetOrder ? "success" : "warning";

  return (
    <>
      <AddressConfirmationHeader
        headerTitle={getHeaderTitle(titleOverride, isInternetOrder, billingInfo.isComplete)}
        statusVariant={statusVariant}
        showConfirmAction={
          isInternetOrder && !addressConfirmed && !editing && billingInfo.isComplete
        }
        showEditAction={billingInfo.isComplete && !editing}
        onConfirm={handleConfirmAddress}
        onEdit={handleEdit}
      />
      {editing ? (
        <AddressEditForm
          onAddressChange={handleBilingualAddressChange}
          onSave={handleSave}
          onCancel={handleCancel}
          isSaving={isSaving}
          isComplete={isAddressComplete}
          error={error}
        />
      ) : (
        <AddressDisplay
          address={address}
          countryLabel={countryLabel}
          isInternetOrder={isInternetOrder}
          addressConfirmed={addressConfirmed}
          confirmationMessage={confirmationPrompt ?? DEFAULT_CONFIRMATION_PROMPT}
          onEdit={() => handleEdit()}
        />
      )}
    </>
  );
}

export function AddressConfirmation({
  onAddressConfirmed,
  onAddressIncomplete,
  orderType,
  embedded = false,
  titleOverride,
  confirmationPrompt,
}: AddressConfirmationProps) {
  const isInternetOrder = orderType === ORDER_TYPE.INTERNET;
  const state = useAddressConfirmationState(
    onAddressConfirmed,
    onAddressIncomplete,
    isInternetOrder
  );

  const content = (
    <AddressConfirmationContent
      isInternetOrder={isInternetOrder}
      titleOverride={titleOverride}
      confirmationPrompt={confirmationPrompt}
      state={state}
    />
  );

  return embedded ? content : <SubCard className="mb-6">{content}</SubCard>;
}
