import { useEffect, useState, useRef, useMemo } from "react";
import { apiFetch } from '@/utils/api';
import OrderMetricsCard from "../components/purchase-orders/OrderMetricsCard";
import VendorMetricsCard from "../components/purchase-orders/VendorMetricsCard";
import CategoryMetricsCard from "../components/purchase-orders/CategoryMetricsCard";
import PaginationControls from "../components/purchase-orders/PaginationControls";
import PurchaseOrdersTable from "../components/purchase-orders/PurchaseOrdersTable";
import FilterControls from "../components/purchase-orders/FilterControls";
import PipelineCard from "../components/purchase-orders/PipelineCard";

interface PurchaseOrder {
  id: number | string;
  vendor_name: string;
  order_date: string | null;
  receiving_date: string | null;
  status: number;
  total_items: number;
  total_quantity: number;
  total_cost: number;
  total_received: number;
  fulfillment_rate: number;
  short_note: string | null;
  record_type: "po_only" | "po_with_receiving" | "receiving_only";
}

interface VendorMetrics {
  vendor_name: string;
  total_orders: number;
  avg_delivery_days: number;
  max_delivery_days: number;
  fulfillment_rate: number;
  avg_unit_cost: number;
  total_spend: number;
}

interface CostAnalysis {
  unique_products: number;
  avg_cost: number;
  min_cost: number;
  max_cost: number;
  cost_variance: number;
  total_spend_by_category: {
    category: string;
    total_spend: number;
    unique_products?: number;
    avg_cost?: number;
    cost_variance?: number;
  }[];
}

interface ReceivingStatus {
  order_count: number;
  total_ordered: number;
  total_received: number;
  fulfillment_rate: number;
  total_value: number;
  avg_cost: number;
  avg_delivery_days?: number;
  max_delivery_days?: number;
}


export default function PurchaseOrders() {
  const [purchaseOrders, setPurchaseOrders] = useState<PurchaseOrder[]>([]);
  const [, setVendorMetrics] = useState<VendorMetrics[]>([]);
  const [, setCostAnalysis] = useState<CostAnalysis | null>(null);
  const [summary, setSummary] = useState<ReceivingStatus | null>(null);
  const [loading, setLoading] = useState(true);
  const [page, setPage] = useState(1);
  const [sortColumn, setSortColumn] = useState<string>("order_date");
  const [sortDirection, setSortDirection] = useState<"asc" | "desc">("desc");
  const [searchInput, setSearchInput] = useState("");
  const [filterValues, setFilterValues] = useState({
    search: "",
    status: "all",
    vendor: "all",
    recordType: "all",
  });
  const [filterOptions, setFilterOptions] = useState<{
    vendors: string[];
    statuses: number[];
  }>({
    vendors: [],
    statuses: [],
  });
  const [pagination, setPagination] = useState({
    total: 0,
    pages: 0,
    page: 1,
    limit: 100,
  });
  const [] = useState(false);
  const [] = useState<
    number | undefined
  >();
  const [] = useState<
    number | undefined
  >();
  const [] = useState(false);
  const [yearlyVendorData, setYearlyVendorData] = useState<
    {
      vendor: string;
      orders: number;
      total_spend: number;
      percentage?: number;
    }[]
  >([]);
  const [yearlyCategoryData, setYearlyCategoryData] = useState<
    {
      category: string;
      unique_products?: number;
      total_spend: number;
      percentage?: number;
      avg_cost?: number;
      cost_variance?: number;
    }[]
  >([]);
  const [yearlyDataLoading, setYearlyDataLoading] = useState(false);
  const hasInitialFetchRef = useRef(false);
  const hasInitialYearlyFetchRef = useRef(false);

  // Use useMemo to compute filters only when filterValues change
  const filters = useMemo(() => filterValues, [filterValues]);

  const fetchData = async () => {
    try {
      setLoading(true);
      
      // Build search params with proper encoding
      const searchParams = new URLSearchParams();
      searchParams.append('page', page.toString());
      searchParams.append('limit', '100');
      searchParams.append('sortColumn', sortColumn);
      searchParams.append('sortDirection', sortDirection);
      
      if (filters.search) {
        searchParams.append('search', filters.search);
      }
      
      if (filters.status !== 'all') {
        searchParams.append('status', filters.status);
      }
      
      if (filters.vendor !== 'all') {
        searchParams.append('vendor', filters.vendor);
      }
      
      if (filters.recordType !== 'all') {
        searchParams.append('recordType', filters.recordType);
      }

      console.log("Fetching data with params:", searchParams.toString());

      // Fetch orders first separately to handle errors better
      const purchaseOrdersRes = await apiFetch(`/api/purchase-orders?${searchParams.toString()}`);
      
      if (!purchaseOrdersRes.ok) {
        const errorText = await purchaseOrdersRes.text();
        console.error("Failed to fetch purchase orders:", errorText);
        throw new Error(`Failed to fetch purchase orders: ${errorText}`);
      }

      const purchaseOrdersData = await purchaseOrdersRes.json();
      
      // Process orders data immediately
      const processedOrders = purchaseOrdersData.orders.map((order: any) => ({
        ...order,
        status: Number(order.status),
        total_items: Number(order.total_items) || 0,
        total_quantity: Number(order.total_quantity) || 0,
        total_cost: Number(order.total_cost) || 0,
        total_received: Number(order.total_received) || 0,
        fulfillment_rate: Number(order.fulfillment_rate) || 0,
      }));
      
      // Update the main data state
      setPurchaseOrders(processedOrders);
      setPagination(purchaseOrdersData.pagination);
      setFilterOptions(purchaseOrdersData.filters);
      
      // Now fetch the additional data in parallel
      const [vendorMetricsRes, costAnalysisRes, deliveryMetricsRes] = await Promise.all([
        apiFetch("/api/purchase-orders/vendor-metrics"),
        apiFetch("/api/purchase-orders/cost-analysis"),
        apiFetch("/api/purchase-orders/delivery-metrics"),
      ]);

      let vendorMetricsData = [];
      let costAnalysisData = {
        unique_products: 0,
        avg_cost: 0,
        min_cost: 0,
        max_cost: 0,
        cost_variance: 0,
        total_spend_by_category: [],
      };
      
      let deliveryMetricsData = {
        avg_delivery_days: 0,
        max_delivery_days: 0
      };

      if (vendorMetricsRes.ok) {
        vendorMetricsData = await vendorMetricsRes.json();
        setVendorMetrics(vendorMetricsData);
      } else {
        console.error(
          "Failed to fetch vendor metrics:",
          await vendorMetricsRes.text()
        );
        setVendorMetrics([]);
      }

      if (costAnalysisRes.ok) {
        costAnalysisData = await costAnalysisRes.json();
        setCostAnalysis(costAnalysisData);
      } else {
        console.error(
          "Failed to fetch cost analysis:",
          await costAnalysisRes.text()
        );
        setCostAnalysis({
          unique_products: 0,
          avg_cost: 0,
          min_cost: 0,
          max_cost: 0,
          cost_variance: 0,
          total_spend_by_category: [],
        });
      }
      
      if (deliveryMetricsRes.ok) {
        deliveryMetricsData = await deliveryMetricsRes.json();
        
        // Merge delivery metrics into summary
        const summaryWithDelivery = {
          ...purchaseOrdersData.summary,
          avg_delivery_days: deliveryMetricsData.avg_delivery_days,
          max_delivery_days: deliveryMetricsData.max_delivery_days
        };
        
        setSummary(summaryWithDelivery);
      } else {
        console.error(
          "Failed to fetch delivery metrics:",
          await deliveryMetricsRes.text()
        );
        setSummary({
          ...purchaseOrdersData.summary,
          avg_delivery_days: 0,
          max_delivery_days: 0
        });
      }

      // Mark that we've completed an initial fetch
      hasInitialFetchRef.current = true;
    } catch (error) {
      console.error("Error fetching data:", error);
      // Set default values in case of error
      setPurchaseOrders([]);
      setPagination({ total: 0, pages: 0, page: 1, limit: 100 });
      setFilterOptions({ vendors: [], statuses: [] });
      setSummary({
        order_count: 0,
        total_ordered: 0,
        total_received: 0,
        fulfillment_rate: 0,
        total_value: 0,
        avg_cost: 0,
      });
      setVendorMetrics([]);
      setCostAnalysis({
        unique_products: 0,
        avg_cost: 0,
        min_cost: 0,
        max_cost: 0,
        cost_variance: 0,
        total_spend_by_category: [],
      });
    } finally {
      setLoading(false);
    }
  };

  // Setup debounced search
  useEffect(() => {
    const timer = setTimeout(() => {
      if (searchInput !== filterValues.search) {
        setFilterValues(prev => ({ ...prev, search: searchInput }));
      }
    }, 300); // Use 300ms for better response time
    
    return () => clearTimeout(timer);
  }, [searchInput, filterValues.search]);

  // Reset page to 1 when filters change
  useEffect(() => {
    // Reset to page 1 when filters change to ensure proper pagination
    setPage(1);
  }, [filterValues]); // Use filterValues directly to avoid unnecessary renders

  // Fetch data when page, sort or filters change
  useEffect(() => {
    // Log the current filter state for debugging
    console.log("Fetching with filters:", filterValues);
    console.log("Page:", page, "Sort:", sortColumn, sortDirection);
    
    // Always fetch data - don't use conditional checks that might prevent it
    fetchData();
  }, [page, sortColumn, sortDirection, filterValues]);

  // Handle column sorting more consistently
  const handleSort = (column: string) => {
    // Reset to page 1 when changing sort to ensure we see the first page of results
    setPage(1);
    
    if (sortColumn === column) {
      setSortDirection((prev) => (prev === "asc" ? "desc" : "asc"));
    } else {
      setSortColumn(column);
      // For most columns, start with descending to show highest values first
      if (column === 'id' || column === 'vendor_name') {
        setSortDirection("asc");
      } else {
        setSortDirection("desc");
      }
    }
  };
  
  // Update filter handlers
  const handleStatusChange = (value: string) => {
    setFilterValues(prev => ({ ...prev, status: value }));
  };
  
  const handleVendorChange = (value: string) => {
    setFilterValues(prev => ({ ...prev, vendor: value }));
  };
  
  const handleRecordTypeChange = (value: string) => {
    setFilterValues(prev => ({ ...prev, recordType: value }));
  };

  // Clear all filters handler
  const clearFilters = () => {
    setSearchInput("");
    setFilterValues({
      search: "",
      status: "all",
      vendor: "all",
      recordType: "all",
    });
  };

  // Update this function to fetch yearly data
  const fetchYearlyData = async () => {
    if (
      hasInitialYearlyFetchRef.current &&
      import.meta.hot &&
      (yearlyVendorData.length > 0 || yearlyCategoryData.length > 0)
    ) {
      return;
    }

    try {
      setYearlyDataLoading(true);

      // Create a date for 1 year ago
      const oneYearAgo = new Date();
      oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);
      const dateParam = oneYearAgo.toISOString().split("T")[0]; // Format as YYYY-MM-DD

      const [vendorResponse, categoryResponse] = await Promise.all([
        apiFetch(`/api/purchase-orders/vendor-analysis?since=${dateParam}`),
        apiFetch(`/api/purchase-orders/category-analysis?since=${dateParam}`),
      ]);

      if (vendorResponse.ok) {
        const vendorData = await vendorResponse.json();
        // Calculate percentages before setting state
        const totalSpend = vendorData.reduce(
          (sum: number, v: any) => sum + v.total_spend,
          0
        );

        setYearlyVendorData(
          vendorData.map((v: any) => ({
            ...v,
            percentage: totalSpend > 0 ? v.total_spend / totalSpend : 0,
          }))
        );
      } else {
        console.error(
          "Failed to fetch yearly vendor data:",
          await vendorResponse.text()
        );
      }

      if (categoryResponse.ok) {
        const categoryData = await categoryResponse.json();
        // Calculate percentages before setting state
        const totalSpend = categoryData.reduce(
          (sum: number, c: any) => sum + c.total_spend,
          0
        );

        setYearlyCategoryData(
          categoryData.map((c: any) => ({
            ...c,
            percentage: totalSpend > 0 ? c.total_spend / totalSpend : 0,
          }))
        );
      } else {
        console.error(
          "Failed to fetch yearly category data:",
          await categoryResponse.text()
        );
      }

      // Mark that we've completed an initial fetch
      hasInitialYearlyFetchRef.current = true;
    } catch (error) {
      console.error("Error fetching yearly data:", error);
    } finally {
      setYearlyDataLoading(false);
    }
  };

  // Fetch yearly data when component mounts, not just when dialogs open
  useEffect(() => {
    fetchYearlyData();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <div className="container mx-auto py-6">
      <h1 className="mb-6 text-3xl font-bold">Purchase Orders</h1>

      <div className="mb-4 grid gap-4 md:grid-cols-3">
        <OrderMetricsCard
          summary={summary}
          loading={loading}
        />
        <VendorMetricsCard
          loading={loading}
          yearlyVendorData={yearlyVendorData}
          yearlyDataLoading={yearlyDataLoading}
        />
        <CategoryMetricsCard
          loading={loading}
          yearlyCategoryData={yearlyCategoryData}
          yearlyDataLoading={yearlyDataLoading}
        />
      </div>

      <div className="mb-4">
        <PipelineCard />
      </div>

      <FilterControls
        searchInput={searchInput}
        setSearchInput={setSearchInput}
        filterValues={filterValues}
        handleStatusChange={handleStatusChange}
        handleVendorChange={handleVendorChange}
        handleRecordTypeChange={handleRecordTypeChange}
        clearFilters={clearFilters}
        filterOptions={filterOptions}
        loading={loading}
      />

      <PurchaseOrdersTable
        purchaseOrders={purchaseOrders}
        loading={loading}
        summary={summary}
        sortColumn={sortColumn}
        sortDirection={sortDirection}
        handleSort={handleSort}
      />

      <PaginationControls 
        pagination={pagination}
        currentPage={page}
        onPageChange={setPage}
      />
    </div>
  );
}
