import { Layout } from "@/components/layout/Layout";
import { ImageIcon, Loader2, X } from "lucide-react";
import { useState, useEffect, type ReactElement } from "react";
import { useAppSelector, useAppDispatch } from "@/hooks/redux-hooks";
import { tenantService } from "@/services/tenant-service";
import { fileService } from "@/services/file-service";
import { showToast } from "@/utils/toast";
import { updateTheme } from "@/store/themeSlice";
import { PrimaryButton, AuthenticatedImage } from "@/components/shared";
import { generateUUID } from "@/lib/utils";
import type { Tenant } from "@/types/tenant";

// Helper function to get base URL with protocol
const getBaseUrlWithProtocol = (): string => {
  return import.meta.env.VITE_API_BASE_URL || "http://localhost:3000";
};

export interface SettingsProps {
  customTenantId?: string;
  hideLayout?: boolean;
}

const Settings = ({ customTenantId, hideLayout = false }: SettingsProps = {}): ReactElement => {
  const authTenantId = useAppSelector((state) => state.auth.tenantId);
  const tenantId = customTenantId || authTenantId;
  const dispatch = useAppDispatch();

  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [isSaving, setIsSaving] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);

  // Tenant data
  const [tenant, setTenant] = useState<Tenant | null>(null);

  // Color states
  const [primaryColor, setPrimaryColor] = useState<string>("#112868");
  const [secondaryColor, setSecondaryColor] = useState<string>("#23DCE1");
  const [accentColor, setAccentColor] = useState<string>("#084CC8");

  // Logo states
  const [logoFile, setLogoFile] = useState<File | null>(null);
  const [logoFilePath, setLogoFilePath] = useState<string | null>(null);
  const [logoFileAttachmentUuid, setLogoFileAttachmentUuid] = useState<
    string | null
  >(null);
  const [logoFileUrl, setLogoFileUrl] = useState<string | null>(null);
  const [logoPreviewUrl, setLogoPreviewUrl] = useState<string | null>(null);
  const [isUploadingLogo, setIsUploadingLogo] = useState<boolean>(false);

  // Favicon states
  const [faviconFile, setFaviconFile] = useState<File | null>(null);
  const [faviconFilePath, setFaviconFilePath] = useState<string | null>(null);
  const [faviconFileAttachmentUuid, setFaviconFileAttachmentUuid] = useState<
    string | null
  >(null);
  const [faviconFileUrl, setFaviconFileUrl] = useState<string | null>(null);
  const [faviconPreviewUrl, setFaviconPreviewUrl] = useState<string | null>(
    null,
  );
  const [isUploadingFavicon, setIsUploadingFavicon] = useState<boolean>(false);
  const [logoError, setLogoError] = useState<string | null>(null);
  const [faviconError, setFaviconError] = useState<string | null>(null);

  // Fetch tenant data on mount
  useEffect(() => {
    const fetchTenant = async (): Promise<void> => {
      if (!tenantId) {
        setError("Tenant ID not found");
        setIsLoading(false);
        return;
      }

      try {
        setIsLoading(true);
        setError(null);
        const response = await tenantService.getById(tenantId);

        if (response.success && response.data) {
          const tenantData = response.data;
          setTenant(tenantData);

          // Set colors
          setPrimaryColor(tenantData.primary_color || "#112868");
          setSecondaryColor(tenantData.secondary_color || "#23DCE1");
          setAccentColor(tenantData.accent_color || "#084CC8");

          // Set logo
          if (tenantData.logo_file_path) {
            setLogoFileUrl(tenantData.logo_file_path);
            setLogoFilePath(tenantData.logo_file_path);
            setLogoFileAttachmentUuid(
              tenantData.logo_file_attachment_uuid || null,
            );
            setLogoError(null);
          }

          // Set favicon
          if (tenantData.favicon_file_path) {
            setFaviconFileUrl(tenantData.favicon_file_path);
            setFaviconFilePath(tenantData.favicon_file_path);
            setFaviconFileAttachmentUuid(
              tenantData.favicon_file_attachment_uuid || null,
            );
            setFaviconError(null);
          }
        }
      } catch (err: any) {
        const errorMessage =
          err?.response?.data?.error?.message ||
          err?.response?.data?.message ||
          err?.message ||
          "Failed to load tenant settings";
        setError(errorMessage);
        showToast.error(errorMessage);
      } finally {
        setIsLoading(false);
      }
    };

    fetchTenant();
  }, [tenantId]);

  // Cleanup preview URLs
  useEffect(() => {
    return () => {
      if (logoPreviewUrl) {
        URL.revokeObjectURL(logoPreviewUrl);
      }
      if (faviconPreviewUrl) {
        URL.revokeObjectURL(faviconPreviewUrl);
      }
    };
  }, [logoPreviewUrl, faviconPreviewUrl]);

  const handleLogoChange = async (
    e: React.ChangeEvent<HTMLInputElement>,
  ): Promise<void> => {
    const file = e.target.files?.[0];
    if (!file) return;

    // Validate file size (2MB max)
    if (file.size > 2 * 1024 * 1024) {
      showToast.error("Logo file size must be less than 2MB");
      return;
    }

    // Validate file type
    const validTypes = [
      "image/png",
      "image/svg+xml",
      "image/jpeg",
      "image/jpg",
    ];
    if (!validTypes.includes(file.type)) {
      showToast.error("Logo must be PNG, SVG, or JPG format");
      return;
    }

    // Revoke previous preview URL
    if (logoPreviewUrl) {
      URL.revokeObjectURL(logoPreviewUrl);
    }

    const previewUrl = URL.createObjectURL(file);
    setLogoFile(file);
    setLogoPreviewUrl(previewUrl);
    setIsUploadingLogo(true);

    try {
      const response = await fileService.upload(
        file,
        "tenant",
        generateUUID(),
        tenantId || undefined,
      );
      const fileId = response.data.id;
      setLogoFileAttachmentUuid(fileId);

      const baseUrl = getBaseUrlWithProtocol();
      const formattedUrl = `${baseUrl}/files/${fileId}/preview`;
      setLogoFilePath(formattedUrl);
      setLogoFileUrl(formattedUrl);

      setLogoError(null);
      showToast.success("Logo uploaded successfully");
    } catch (err: any) {
      const errorMessage =
        err?.response?.data?.error?.message ||
        err?.response?.data?.message ||
        err?.message ||
        "Failed to upload logo. Please try again.";
      showToast.error(errorMessage);
      setLogoFile(null);
      URL.revokeObjectURL(previewUrl);
      setLogoPreviewUrl(null);
      setLogoFileUrl(null);
      setLogoFilePath(null);
      setLogoFileAttachmentUuid(null);
    } finally {
      setIsUploadingLogo(false);
    }
  };

  const handleFaviconChange = async (
    e: React.ChangeEvent<HTMLInputElement>,
  ): Promise<void> => {
    const file = e.target.files?.[0];
    if (!file) return;

    // Validate file size (500KB max)
    if (file.size > 500 * 1024) {
      showToast.error("Favicon file size must be less than 500KB");
      return;
    }

    // Validate file type
    const validTypes = [
      "image/x-icon",
      "image/png",
      "image/vnd.microsoft.icon",
    ];
    if (!validTypes.includes(file.type)) {
      showToast.error("Favicon must be ICO or PNG format");
      return;
    }

    // Revoke previous preview URL
    if (faviconPreviewUrl) {
      URL.revokeObjectURL(faviconPreviewUrl);
    }

    const previewUrl = URL.createObjectURL(file);
    setFaviconFile(file);
    setFaviconPreviewUrl(previewUrl);
    setIsUploadingFavicon(true);

    try {
      const response = await fileService.upload(
        file,
        "tenant",
        generateUUID(),
        tenantId || undefined,
      );
      const fileId = response.data.id;
      setFaviconFileAttachmentUuid(fileId);

      const baseUrl = getBaseUrlWithProtocol();
      const formattedUrl = `${baseUrl}/files/${fileId}/preview`;
      setFaviconFilePath(formattedUrl);
      setFaviconFileUrl(formattedUrl);

      setFaviconError(null);
      showToast.success("Favicon uploaded successfully");
    } catch (err: any) {
      const errorMessage =
        err?.response?.data?.error?.message ||
        err?.response?.data?.message ||
        err?.message ||
        "Failed to upload favicon. Please try again.";
      showToast.error(errorMessage);
      setFaviconFile(null);
      URL.revokeObjectURL(previewUrl);
      setFaviconPreviewUrl(null);
      setFaviconFileUrl(null);
      setFaviconFilePath(null);
      setFaviconFileAttachmentUuid(null);
    } finally {
      setIsUploadingFavicon(false);
    }
  };

  const handleDeleteLogo = (): void => {
    if (logoPreviewUrl) {
      URL.revokeObjectURL(logoPreviewUrl);
    }
    setLogoFile(null);
    setLogoPreviewUrl(null);
    setLogoFileUrl(null);
    setLogoFilePath(null);
    setLogoFileAttachmentUuid(null);
    setLogoError(null);
    // Reset the file input
    const fileInput = document.getElementById(
      "logo-upload",
    ) as HTMLInputElement;
    if (fileInput) {
      fileInput.value = "";
    }
  };

  const handleDeleteFavicon = (): void => {
    if (faviconPreviewUrl) {
      URL.revokeObjectURL(faviconPreviewUrl);
    }
    setFaviconFile(null);
    setFaviconPreviewUrl(null);
    setFaviconFileUrl(null);
    setFaviconFilePath(null);
    setFaviconFileAttachmentUuid(null);
    setFaviconError(null);
    // Reset the file input
    const fileInput = document.getElementById(
      "favicon-upload",
    ) as HTMLInputElement;
    if (fileInput) {
      fileInput.value = "";
    }
  };

  const handleSave = async (): Promise<void> => {
    if (!tenantId || !tenant) return;

    // Validate logo and favicon are uploaded
    setLogoError(null);
    setFaviconError(null);

    const isLogoMissing = !logoFilePath;
    const isFaviconMissing = !faviconFilePath;

    if (isLogoMissing) {
      setLogoError("Logo is required");
    }

    if (isFaviconMissing) {
      setFaviconError("Favicon is required");
    }

    if (isLogoMissing || isFaviconMissing) {
      return;
    }

    try {
      setIsSaving(true);
      setError(null);

      // Build update data matching EditTenantModal format
      const existingSettings =
        (tenant.settings as Record<string, unknown>) || {};
      const existingContact =
        (existingSettings.contact as Record<string, unknown>) || {};

      const updateData = {
        name: tenant.name,
        slug: tenant.slug,
        status: tenant.status,
        domain: tenant.domain || null,
        subscription_tier: tenant.subscription_tier || null,
        max_users: tenant.max_users || null,
        max_modules: tenant.max_modules || null,
        settings: {
          enable_sso: tenant.enable_sso || false,
          enable_2fa: tenant.enable_2fa || false,
          contact: existingContact,
          branding: {
            primary_color: primaryColor || undefined,
            secondary_color: secondaryColor || undefined,
            accent_color: accentColor || undefined,
            logo_file_path: logoFilePath || undefined,
            logo_file_attachment_uuid: logoFileAttachmentUuid || undefined,
            favicon_file_path: faviconFilePath || undefined,
            favicon_file_attachment_uuid:
              faviconFileAttachmentUuid || undefined,
          },
        },
      };

      const response = await tenantService.update(tenantId, updateData);

      if (response.success) {
        showToast.success("Settings updated successfully");

        // Update theme in Redux for the active session, if not editing a different tenant context
        if (!customTenantId || customTenantId === authTenantId) {
          dispatch(
            updateTheme({
              logo_file_path: logoFilePath,
              favicon_file_path: faviconFilePath,
              primary_color: primaryColor,
              secondary_color: secondaryColor,
              accent_color: accentColor,
            }),
          );
        }

        // Update local tenant state
        setTenant({
          ...tenant,
          primary_color: primaryColor,
          secondary_color: secondaryColor,
          accent_color: accentColor,
          logo_file_path: logoFilePath,
          logo_file_attachment_uuid: logoFileAttachmentUuid,
          favicon_file_path: faviconFilePath,
          favicon_file_attachment_uuid: faviconFileAttachmentUuid,
        });
      }
    } catch (err: any) {
      const errorMessage =
        err?.response?.data?.error?.message ||
        err?.response?.data?.message ||
        err?.message ||
        "Failed to update settings. Please try again.";
      setError(errorMessage);
      showToast.error(errorMessage);
    } finally {
      setIsSaving(false);
    }
  };

  if (isLoading) {
    return (
      <Layout
        currentPage="Settings"
        pageHeader={{
          title: "Settings",
          description: "Manage your tenant settings",
        }}
      >
        <div className="flex items-center justify-center py-12">
          <Loader2 className="w-6 h-6 text-[#112868] animate-spin" />
        </div>
      </Layout>
    );
  }

  if (error && !tenant) {
    return (
      <Layout
        currentPage="Settings"
        pageHeader={{
          title: "Settings",
          description: "Manage your tenant settings",
        }}
      >
        <div className="p-4 bg-[rgba(239,68,68,0.1)] border border-[#ef4444] rounded-md">
          <p className="text-sm text-[#ef4444]">{error}</p>
        </div>
      </Layout>
    );
  }

  const content = (
    <div className="flex flex-col gap-6 w-full h-full">
      {error && (
        <div className="p-4 bg-[rgba(239,68,68,0.1)] border border-[#ef4444] rounded-md">
          <p className="text-sm text-[#ef4444]">{error}</p>
        </div>
      )}

      {/* Branding Section */}
        <div className="bg-white border border-[rgba(0,0,0,0.08)] rounded-lg p-4 md:p-6 flex flex-col gap-4">
          {/* Section Header */}
          <div className="flex flex-col gap-1">
            <h3 className="text-base font-semibold text-[#0f1724]">Branding</h3>
            <p className="text-sm font-normal text-[#9ca3af]">
              Customize logo, favicon, and colors for this tenant experience.
            </p>
          </div>

          {/* Logo and Favicon Upload */}
          <div className="grid grid-cols-1 md:grid-cols-2 gap-5">
            {/* Company Logo */}
            <div className="flex flex-col gap-2">
              <label className="text-sm font-medium text-[#0f1724]">
                Company Logo <span className="text-[#e02424]">*</span>
              </label>
              <label
                htmlFor="logo-upload"
                className="bg-[#f5f7fa] border border-dashed border-[#d1d5db] rounded-md p-4 flex gap-4 items-center cursor-pointer hover:bg-[#e5e7eb] transition-colors"
              >
                <div className="bg-white border border-[#d1d5db] rounded-lg size-12 flex items-center justify-center shrink-0">
                  {isUploadingLogo ? (
                    <Loader2 className="w-5 h-5 text-[#6b7280] animate-spin" />
                  ) : (
                    <ImageIcon className="w-5 h-5 text-[#6b7280]" />
                  )}
                </div>
                <div className="flex flex-col gap-0.5 flex-1 min-w-0">
                  <span className="text-sm font-medium text-[#0f1724]">
                    Upload Logo
                  </span>
                  <span className="text-xs font-normal text-[#9ca3af]">
                    PNG, SVG, JPG up to 2MB.
                  </span>
                </div>
                <input
                  id="logo-upload"
                  type="file"
                  accept="image/png,image/svg+xml,image/jpeg,image/jpg"
                  onChange={handleLogoChange}
                  className="hidden"
                  disabled={isUploadingLogo}
                />
              </label>
              {logoError && (
                <p className="text-sm text-[#ef4444]">{logoError}</p>
              )}
              {(logoFile || logoFileUrl) && (
                <div className="flex flex-col gap-2 mt-1">
                  {logoFile && (
                    <div className="text-xs text-[#6b7280]">
                      {isUploadingLogo
                        ? "Uploading..."
                        : `Selected: ${logoFile.name}`}
                    </div>
                  )}
                  {(logoPreviewUrl || logoFileUrl) && (
                    <div className="mt-2 relative inline-block">
                      <AuthenticatedImage
                        fileId={logoFileAttachmentUuid}
                        src={logoPreviewUrl || logoFileUrl}
                        alt="Logo preview"
                        className="max-w-full h-20 object-contain border border-[#d1d5db] rounded-md p-2 bg-white"
                        style={{ display: "block", maxHeight: "80px" }}
                      />
                      <button
                        type="button"
                        onClick={handleDeleteLogo}
                        className="absolute top-1 right-1 bg-[#ef4444] text-white rounded-full p-1 hover:bg-[#dc2626] transition-colors"
                        aria-label="Delete logo"
                      >
                        <X className="w-3 h-3" />
                      </button>
                    </div>
                  )}
                </div>
              )}
            </div>

            {/* Favicon */}
            <div className="flex flex-col gap-2">
              <label className="text-sm font-medium text-[#0f1724]">
                Favicon <span className="text-[#e02424]">*</span>
              </label>
              <label
                htmlFor="favicon-upload"
                className="bg-[#f5f7fa] border border-dashed border-[#d1d5db] rounded-md p-4 flex gap-4 items-center cursor-pointer hover:bg-[#e5e7eb] transition-colors"
              >
                <div className="bg-white border border-[#d1d5db] rounded-lg size-12 flex items-center justify-center shrink-0">
                  {isUploadingFavicon ? (
                    <Loader2 className="w-5 h-5 text-[#6b7280] animate-spin" />
                  ) : (
                    <ImageIcon className="w-5 h-5 text-[#6b7280]" />
                  )}
                </div>
                <div className="flex flex-col gap-0.5 flex-1 min-w-0">
                  <span className="text-sm font-medium text-[#0f1724]">
                    Upload Favicon
                  </span>
                  <span className="text-xs font-normal text-[#9ca3af]">
                    ICO or PNG up to 500KB.
                  </span>
                </div>
                <input
                  id="favicon-upload"
                  type="file"
                  accept="image/x-icon,image/png,image/vnd.microsoft.icon"
                  onChange={handleFaviconChange}
                  className="hidden"
                  disabled={isUploadingFavicon}
                />
              </label>
              {faviconError && (
                <p className="text-sm text-[#ef4444]">{faviconError}</p>
              )}
              {(faviconFile || faviconFileUrl) && (
                <div className="flex flex-col gap-2 mt-1">
                  {faviconFile && (
                    <div className="text-xs text-[#6b7280]">
                      {isUploadingFavicon
                        ? "Uploading..."
                        : `Selected: ${faviconFile.name}`}
                    </div>
                  )}
                  {(faviconPreviewUrl || faviconFileUrl) && (
                    <div className="mt-2 relative inline-block">
                      <AuthenticatedImage
                        fileId={faviconFileAttachmentUuid}
                        src={faviconPreviewUrl || faviconFileUrl}
                        alt="Favicon preview"
                        className="w-16 h-16 object-contain border border-[#d1d5db] rounded-md p-2 bg-white"
                        style={{
                          display: "block",
                          width: "64px",
                          height: "64px",
                        }}
                      />
                      <button
                        type="button"
                        onClick={handleDeleteFavicon}
                        className="absolute top-1 right-1 bg-[#ef4444] text-white rounded-full p-1 hover:bg-[#dc2626] transition-colors"
                        aria-label="Delete favicon"
                      >
                        <X className="w-3 h-3" />
                      </button>
                    </div>
                  )}
                </div>
              )}
            </div>
          </div>

          {/* Primary Color */}
          <div className="flex flex-col gap-2">
            <label className="text-sm font-medium text-[#0f1724]">
              Primary Color
            </label>
            <div className="flex gap-3 items-center">
              <div
                className="border border-[#d1d5db] rounded-md size-10 shrink-0"
                style={{ backgroundColor: primaryColor }}
              />
              <div className="flex-1">
                <input
                  type="text"
                  value={primaryColor}
                  onChange={(e) => setPrimaryColor(e.target.value)}
                  className="bg-[#f5f7fa] border border-[#d1d5db] h-10 px-3 py-1 rounded-md text-sm text-[#0f1724] w-full focus:outline-none focus:ring-2 focus:ring-[#112868] focus:border-transparent"
                  placeholder="#112868"
                />
              </div>
              <input
                type="color"
                value={primaryColor}
                onChange={(e) => setPrimaryColor(e.target.value)}
                className="size-10 rounded-md border border-[#d1d5db] cursor-pointer"
              />
            </div>
            <p className="text-xs font-normal text-[#9ca3af]">
              Used for navigation, headers, and key actions.
            </p>
          </div>

          {/* Secondary and Accent Colors */}
          <div className="grid grid-cols-1 md:grid-cols-2 gap-5">
            {/* Secondary Color */}
            <div className="flex flex-col gap-2">
              <label className="text-sm font-medium text-[#0f1724]">
                Secondary Color
              </label>
              <div className="flex gap-3 items-center">
                <div
                  className="border border-[#d1d5db] rounded-md size-10 shrink-0"
                  style={{ backgroundColor: secondaryColor }}
                />
                <div className="flex-1">
                  <input
                    type="text"
                    value={secondaryColor}
                    onChange={(e) => setSecondaryColor(e.target.value)}
                    className="bg-[#f5f7fa] border border-[#d1d5db] h-10 px-3 py-1 rounded-md text-sm text-[#0f1724] w-full focus:outline-none focus:ring-2 focus:ring-[#112868] focus:border-transparent"
                    placeholder="#23DCE1"
                  />
                </div>
                <input
                  type="color"
                  value={secondaryColor}
                  onChange={(e) => setSecondaryColor(e.target.value)}
                  className="size-10 rounded-md border border-[#d1d5db] cursor-pointer"
                />
              </div>
              <p className="text-xs font-normal text-[#9ca3af]">
                Used for highlights and supporting elements.
              </p>
            </div>

            {/* Accent Color */}
            <div className="flex flex-col gap-2">
              <label className="text-sm font-medium text-[#0f1724]">
                Accent Color
              </label>
              <div className="flex gap-3 items-center">
                <div
                  className="border border-[#d1d5db] rounded-md size-10 shrink-0"
                  style={{ backgroundColor: accentColor }}
                />
                <div className="flex-1">
                  <input
                    type="text"
                    value={accentColor}
                    onChange={(e) => setAccentColor(e.target.value)}
                    className="bg-[#f5f7fa] border border-[#d1d5db] h-10 px-3 py-1 rounded-md text-sm text-[#0f1724] w-full focus:outline-none focus:ring-2 focus:ring-[#112868] focus:border-transparent"
                    placeholder="#084CC8"
                  />
                </div>
                <input
                  type="color"
                  value={accentColor}
                  onChange={(e) => setAccentColor(e.target.value)}
                  className="size-10 rounded-md border border-[#d1d5db] cursor-pointer"
                />
              </div>
              <p className="text-xs font-normal text-[#9ca3af]">
                Used for alerts and special notices.
              </p>
            </div>
          </div>

          {/* Save Button */}
          <div className="flex justify-end pt-4 border-t border-[rgba(0,0,0,0.08)]">
            <PrimaryButton
              onClick={handleSave}
              disabled={isSaving || isUploadingLogo || isUploadingFavicon}
              className="px-6 py-2.5"
            >
              {isSaving ? "Saving..." : "Save Changes"}
            </PrimaryButton>
          </div>
        </div>
      </div>
  );

  if (hideLayout) {
    return content;
  }

  return (
    <Layout
      currentPage="Settings"
      pageHeader={{
        title: "Settings",
        description: "Manage your tenant settings",
      }}
    >
      {content}
    </Layout>
  );
};

export default Settings;
