"use client";

import React, { useEffect, useMemo, useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { apiClient } from "@/core/api";
import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner";
import { Button } from "@/components/atoms/button";

// CSS class constants for toggle switch
const TOGGLE_BASE =
  "relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-[var(--cp-duration-normal)] focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background";
const TOGGLE_ACTIVE = "bg-primary";
const TOGGLE_INACTIVE = "bg-muted";
const TOGGLE_KNOB_BASE =
  "pointer-events-none inline-block h-5 w-5 rounded-full bg-background shadow ring-0";

interface SimFeatureTogglesProps {
  subscriptionId: number;
  voiceMailEnabled?: boolean;
  callWaitingEnabled?: boolean;
  internationalRoamingEnabled?: boolean;
  networkType?: string; // '4G' | '5G'
  onChanged?: () => void;
  embedded?: boolean; // when true, render without outer card wrappers
}

function useFeatureTogglesState(props: SimFeatureTogglesProps) {
  const {
    subscriptionId,
    voiceMailEnabled,
    callWaitingEnabled,
    internationalRoamingEnabled,
    networkType,
    onChanged,
  } = props;

  const initial = useMemo(
    () => ({
      vm: !!voiceMailEnabled,
      cw: !!callWaitingEnabled,
      ir: !!internationalRoamingEnabled,
      nt: (networkType === "5G" ? "5G" : "4G") as "4G" | "5G",
    }),
    [voiceMailEnabled, callWaitingEnabled, internationalRoamingEnabled, networkType]
  );

  const [vm, setVm] = useState(initial.vm);
  const [cw, setCw] = useState(initial.cw);
  const [ir, setIr] = useState(initial.ir);
  const [nt, setNt] = useState<"4G" | "5G">(initial.nt);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState<string | null>(null);

  useEffect(() => {
    setVm(initial.vm);
    setCw(initial.cw);
    setIr(initial.ir);
    setNt(initial.nt);
  }, [initial.vm, initial.cw, initial.ir, initial.nt]);

  const reset = () => {
    setVm(initial.vm);
    setCw(initial.cw);
    setIr(initial.ir);
    setNt(initial.nt);
    setError(null);
    setSuccess(null);
  };

  const applyChanges = async () => {
    setLoading(true);
    setError(null);
    setSuccess(null);
    try {
      const featurePayload = buildFeaturePayload(initial, { vm, cw, ir, nt });
      if (Object.keys(featurePayload).length > 0) {
        await apiClient.POST("/api/subscriptions/{id}/sim/features", {
          params: { path: { id: subscriptionId } },
          body: featurePayload,
        });
      }
      setSuccess("Changes submitted successfully");
      onChanged?.();
    } catch (e: unknown) {
      const devMessage = e instanceof Error ? e.message : "Failed to submit changes";
      setError(
        process.env.NODE_ENV === "development"
          ? devMessage
          : "Unable to submit changes right now. Please try again."
      );
    } finally {
      setLoading(false);
      setTimeout(() => setSuccess(null), 3000);
    }
  };

  return {
    vm,
    setVm,
    cw,
    setCw,
    ir,
    setIr,
    nt,
    setNt,
    loading,
    error,
    success,
    reset,
    applyChanges,
  };
}

export function SimFeatureToggles(props: SimFeatureTogglesProps): React.ReactElement {
  const { embedded = false } = props;
  const state = useFeatureTogglesState(props);
  const cardClasses = embedded
    ? ""
    : "bg-card rounded-xl border border-border shadow-[var(--cp-shadow-1)]";
  const contentClasses = embedded ? "" : "p-6";

  return (
    <div className="space-y-6">
      <div className={cardClasses}>
        <div className={`${contentClasses} space-y-4`}>
          <FeatureToggleRow
            label="Voice Mail"
            description="¥300/month"
            checked={state.vm}
            onChange={() => state.setVm(!state.vm)}
          />
          <FeatureToggleRow
            label="Call Waiting"
            description="¥300/month"
            checked={state.cw}
            onChange={() => state.setCw(!state.cw)}
          />
          <FeatureToggleRow
            label="International Roaming"
            description="Global connectivity"
            checked={state.ir}
            onChange={() => state.setIr(!state.ir)}
          />
          <NetworkTypeSelector nt={state.nt} setNt={state.setNt} />
        </div>
      </div>
      <NotesAndActionsSection
        embedded={embedded}
        success={state.success}
        error={state.error}
        loading={state.loading}
        onApply={() => void state.applyChanges()}
        onReset={state.reset}
      />
    </div>
  );
}

// ============================================================================
// Helper Functions
// ============================================================================

interface FeatureState {
  vm: boolean;
  cw: boolean;
  ir: boolean;
  nt: "4G" | "5G";
}

function buildFeaturePayload(
  initial: FeatureState,
  current: FeatureState
): {
  voiceMailEnabled?: boolean;
  callWaitingEnabled?: boolean;
  internationalRoamingEnabled?: boolean;
  networkType?: "4G" | "5G";
} {
  const payload: {
    voiceMailEnabled?: boolean;
    callWaitingEnabled?: boolean;
    internationalRoamingEnabled?: boolean;
    networkType?: "4G" | "5G";
  } = {};

  if (current.vm !== initial.vm) payload.voiceMailEnabled = current.vm;
  if (current.cw !== initial.cw) payload.callWaitingEnabled = current.cw;
  if (current.ir !== initial.ir) payload.internationalRoamingEnabled = current.ir;
  if (current.nt !== initial.nt) payload.networkType = current.nt;

  return payload;
}

// ============================================================================
// Sub-Components
// ============================================================================

interface FeatureToggleRowProps {
  label: string;
  description: string;
  checked: boolean;
  onChange: () => void;
}

function FeatureToggleRow({
  label,
  description,
  checked,
  onChange,
}: FeatureToggleRowProps): React.ReactElement {
  const toggleBgClass = checked ? TOGGLE_ACTIVE : TOGGLE_INACTIVE;

  return (
    <div className="flex items-center justify-between py-4">
      <div className="flex-1">
        <div className="text-sm font-medium text-foreground">{label}</div>
        <div className="text-xs text-muted-foreground">{description}</div>
      </div>
      <button
        type="button"
        role="switch"
        aria-checked={checked}
        onClick={onChange}
        className={`${TOGGLE_BASE} ${toggleBgClass}`}
      >
        <motion.span
          className={TOGGLE_KNOB_BASE}
          animate={{ x: checked ? 20 : 0 }}
          transition={{ type: "spring", stiffness: 500, damping: 30 }}
        />
      </button>
    </div>
  );
}

interface NetworkTypeSelectorProps {
  nt: "4G" | "5G";
  setNt: (value: "4G" | "5G") => void;
}

function NetworkTypeSelector({ nt, setNt }: NetworkTypeSelectorProps): React.ReactElement {
  const options: Array<"4G" | "5G"> = ["4G", "5G"];

  return (
    <div className="border-t border-border pt-6">
      <div className="mb-4">
        <div className="text-sm font-medium text-foreground mb-1">Network Type</div>
        <div className="text-xs text-muted-foreground">Choose your preferred connectivity</div>
        <div className="text-xs text-danger mt-1">
          Voice, network, and plan changes must be requested at least 30 minutes apart. If you just
          changed another option, you may need to wait before submitting.
        </div>
      </div>
      <div
        className="inline-flex rounded-lg bg-muted/60 p-1"
        role="radiogroup"
        aria-label="Network Type"
      >
        {options.map(value => (
          <button
            key={value}
            type="button"
            role="radio"
            aria-checked={nt === value}
            onClick={() => setNt(value)}
            className="relative rounded-md px-6 py-1.5 text-sm font-medium transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background"
          >
            {nt === value && (
              <motion.div
                layoutId="network-type-indicator"
                className="absolute inset-0 rounded-md bg-background shadow-sm"
                transition={{ type: "spring", stiffness: 400, damping: 30 }}
              />
            )}
            <span
              className={`relative z-10 ${nt === value ? "text-foreground" : "text-muted-foreground"}`}
            >
              {value}
            </span>
          </button>
        ))}
      </div>
      <p className="text-xs text-muted-foreground mt-2">5G connectivity for enhanced speeds</p>
    </div>
  );
}

interface NotesAndActionsSectionProps {
  embedded: boolean;
  success: string | null;
  error: string | null;
  loading: boolean;
  onApply: () => void;
  onReset: () => void;
}

function NotesAndActionsSection({
  embedded,
  success,
  error,
  loading,
  onApply,
  onReset,
}: NotesAndActionsSectionProps): React.ReactElement {
  const containerClasses = embedded
    ? ""
    : "bg-card rounded-xl border border-border p-6 shadow-[var(--cp-shadow-1)]";

  return (
    <div className={containerClasses}>
      <AlertBanner variant="info" title="Important Notes" size="sm">
        <ul className="space-y-1 text-xs">
          <li>Changes take effect approximately 30 minutes after submission.</li>
          <li>You may need to restart your device after changes are applied.</li>
          <li>
            <span className="font-medium">
              Voice, network, and plan changes must be requested at least 30 minutes apart.
            </span>
          </li>
          <li>Voice Mail / Call Waiting changes must be requested before the 25th of the month.</li>
        </ul>
      </AlertBanner>

      <AnimatePresence>
        {success && (
          <motion.div
            key="success-banner"
            initial={{ opacity: 0, height: 0, y: -8 }}
            animate={{ opacity: 1, height: "auto", y: 0 }}
            exit={{ opacity: 0, height: 0, y: -8 }}
            transition={{ duration: 0.25, ease: "easeInOut" }}
            className="mb-4 overflow-hidden"
          >
            <AlertBanner variant="success" title="Success" size="sm" elevated>
              {success}
            </AlertBanner>
          </motion.div>
        )}
        {error && (
          <motion.div
            key="error-banner"
            initial={{ opacity: 0, height: 0, y: -8 }}
            animate={{ opacity: 1, height: "auto", y: 0 }}
            exit={{ opacity: 0, height: 0, y: -8 }}
            transition={{ duration: 0.25, ease: "easeInOut" }}
            className="mb-4 overflow-hidden"
          >
            <AlertBanner variant="error" title="Unable to apply changes" size="sm" elevated>
              {error}
            </AlertBanner>
          </motion.div>
        )}
      </AnimatePresence>

      <div className="flex flex-col sm:flex-row gap-3">
        <Button className="flex-1" onClick={onApply} loading={loading} loadingText="Applying…">
          Apply Changes
        </Button>
        <Button
          className="flex-1 sm:flex-none"
          variant="outline"
          onClick={onReset}
          disabled={loading}
        >
          Reset
        </Button>
      </div>
    </div>
  );
}
