"use client";

import React, { useEffect, useMemo, useState } from "react";
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 transform rounded-full bg-background shadow ring-0 transition duration-[var(--cp-duration-normal)] ease-in-out";
const TOGGLE_KNOB_ON = "translate-x-5";
const TOGGLE_KNOB_OFF = "translate-x-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;
  const knobPositionClass = checked ? TOGGLE_KNOB_ON : TOGGLE_KNOB_OFF;

  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}`}
      >
        <span className={`${TOGGLE_KNOB_BASE} ${knobPositionClass}`} />
      </button>
    </div>
  );
}

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

function NetworkTypeSelector({ nt, setNt }: NetworkTypeSelectorProps): React.ReactElement {
  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="flex gap-4">
        <NetworkRadioOption id="4g" value="4G" label="4G" checked={nt === "4G"} onChange={setNt} />
        <NetworkRadioOption id="5g" value="5G" label="5G" checked={nt === "5G"} onChange={setNt} />
      </div>
      <p className="text-xs text-muted-foreground mt-2">5G connectivity for enhanced speeds</p>
    </div>
  );
}

interface NetworkRadioOptionProps {
  id: string;
  value: "4G" | "5G";
  label: string;
  checked: boolean;
  onChange: (value: "4G" | "5G") => void;
}

function NetworkRadioOption({
  id,
  value,
  label,
  checked,
  onChange,
}: NetworkRadioOptionProps): React.ReactElement {
  return (
    <div className="flex items-center space-x-2">
      <input
        type="radio"
        id={id}
        name="networkType"
        value={value}
        checked={checked}
        onChange={() => onChange(value)}
        className="h-4 w-4 text-primary focus:ring-ring border-input"
      />
      <label htmlFor={id} className="text-sm text-foreground/80">
        {label}
      </label>
    </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>

      {success && (
        <div className="mb-4">
          <AlertBanner variant="success" title="Success" size="sm" elevated>
            {success}
          </AlertBanner>
        </div>
      )}

      {error && (
        <div className="mb-4">
          <AlertBanner variant="error" title="Unable to apply changes" size="sm" elevated>
            {error}
          </AlertBanner>
        </div>
      )}

      <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>
  );
}
