// src/pages/admin/components/AdminBrandManager.tsx
import React, { useState } from 'react';
import toast from 'react-hot-toast';
import { uploadBrandLogo } from '../../../services/apiClient';
import { Brand } from '../../../types';
import { ErrorDisplay } from '../../../components/ErrorDisplay';
import { useBrandsQuery } from '../../../hooks/queries/useBrandsQuery';
import { logger } from '../../../services/logger.client';

export const AdminBrandManager: React.FC = () => {
  const { data: initialBrands, isLoading: loading, error } = useBrandsQuery();

  // This state will hold a modified list of brands only after an optimistic update (e.g., logo upload).
  // It starts as null, indicating that we should use the original data from the API.
  const [updatedBrands, setUpdatedBrands] = useState<Brand[] | null>(null);

  // At render time, decide which data to display. If updatedBrands exists, it takes precedence.
  // Otherwise, fall back to the initial data from the hook. Default to an empty array.
  const brandsToRender: Brand[] = updatedBrands || initialBrands || [];
  logger.debug(
    {
      loading,
      error: error?.message,
      hasInitialBrands: !!initialBrands,
      hasUpdatedBrands: !!updatedBrands,
      brandsToRenderCount: brandsToRender.length,
    },
    '[AdminBrandManager] Render',
  );

  // The file parameter is now optional to handle cases where the user cancels the file picker.
  const handleLogoUpload = async (brandId: number, file: File | undefined) => {
    if (!file) {
      // This check is now the single source of truth for a missing file.
      logger.debug('[AdminBrandManager] handleLogoUpload called with no file. Showing error toast');
      toast.error('Please select a file to upload.');
      return;
    }

    if (!['image/png', 'image/jpeg', 'image/webp', 'image/svg+xml'].includes(file.type)) {
      toast.error('Invalid file type. Please upload a PNG, JPG, WEBP, or SVG.');
      return;
    }
    if (file.size > 2 * 1024 * 1024) {
      // 2MB limit
      toast.error('File is too large. Maximum size is 2MB.');
      return;
    }

    const toastId = toast.loading('Uploading logo...');

    try {
      const response = await uploadBrandLogo(brandId, file);
      logger.debug(
        {
          ok: response.ok,
          status: response.status,
          statusText: response.statusText,
        },
        '[AdminBrandManager] Logo upload response received',
      );

      // Check for a successful response before attempting to parse JSON.
      if (!response.ok) {
        const errorBody = await response.text();
        throw new Error(errorBody || `Upload failed with status ${response.status}`);
      }

      const { logoUrl } = await response.json();
      toast.success('Logo updated successfully!', { id: toastId });

      // Optimistically update the UI by setting the updatedBrands state.
      // This update is based on the currently rendered list of brands.
      logger.debug(
        { brandId, logoUrl },
        '[AdminBrandManager] Optimistically updating brand with new logo',
      );
      setUpdatedBrands(
        brandsToRender.map((brand) =>
          brand.brand_id === brandId ? { ...brand, logo_url: logoUrl } : brand,
        ),
      );
    } catch (e) {
      const errorMessage = e instanceof Error ? e.message : String(e);
      toast.error(`Upload failed: ${errorMessage}`, { id: toastId });
    }
  };

  if (loading) {
    logger.debug('[AdminBrandManager] Rendering the loading state');
    return <div className="text-center p-4">Loading brands...</div>;
  }

  if (error) {
    logger.error({ err: error }, '[AdminBrandManager] Rendering the error state');
    return <ErrorDisplay message={`Failed to load brands: ${error.message}`} />;
  }

  return (
    <div className="bg-white dark:bg-gray-800 shadow-md rounded-lg p-6">
      <h2 className="text-2xl font-semibold text-gray-800 dark:text-white mb-4">
        Brand Management
      </h2>
      <div className="overflow-x-auto">
        <table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
          <thead className="bg-gray-50 dark:bg-gray-700">
            <tr>
              <th
                scope="col"
                className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider"
              >
                Logo
              </th>
              <th
                scope="col"
                className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider"
              >
                Brand Name
              </th>
              <th
                scope="col"
                className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider"
              >
                Upload New Logo
              </th>
            </tr>
          </thead>
          <tbody className="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
            {brandsToRender.map((brand) => (
              <tr key={brand.brand_id}>
                <td className="px-6 py-4 whitespace-nowrap">
                  {brand.logo_url ? (
                    <img
                      src={brand.logo_url}
                      alt={`${brand.name} logo`}
                      className="h-10 w-10 object-contain rounded-md bg-gray-100 dark:bg-gray-700 p-1"
                    />
                  ) : (
                    <div className="h-10 w-10 flex items-center justify-center bg-gray-200 dark:bg-gray-700 rounded-md text-gray-400 text-xs">
                      No Logo
                    </div>
                  )}
                </td>
                <td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-white">
                  {brand.name}
                  {brand.store_name && (
                    <span className="ml-2 text-xs text-gray-500 dark:text-gray-400">
                      ({brand.store_name})
                    </span>
                  )}
                </td>
                <td className="px-6 py-4 whitespace-nowrap text-sm">
                  <input
                    // Add an accessible label to make the input findable in tests.
                    aria-label={`Upload logo for ${brand.name}`}
                    type="file"
                    accept="image/png, image/jpeg, image/webp, image/svg+xml"
                    // The onChange handler now always calls handleLogoUpload.
                    // Optional chaining (`?.`) safely passes the first file or `undefined`.
                    onChange={(e) => handleLogoUpload(brand.brand_id, e.target.files?.[0])}
                    className="text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-brand-light file:text-brand-dark hover:file:bg-brand-primary/20"
                  />
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
};
