import { useState, useEffect } from 'react';
import type { ReactElement } from 'react';
import { Layout } from '@/components/layout/Layout';
import {
  ViewAuditLogModal,
  DataTable,
  Pagination,
  FilterDropdown,
  StatusBadge,
  type Column,
} from '@/components/shared';
import { Download, ArrowUpDown, Search } from 'lucide-react';
import { auditLogService } from '@/services/audit-log-service';
import { moduleService } from '@/services/module-service';
import type { AuditLog } from '@/types/audit-log';
import { useAppTheme } from '@/hooks/useAppTheme';
import { PrimaryButton } from '@/components/shared';
import { useAppSelector } from '@/hooks/redux-hooks';

// Helper function to format date
const formatDate = (dateString: string): string => {
  const date = new Date(dateString);
  return date.toLocaleDateString('en-US', {
    month: 'short',
    day: 'numeric',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  });
};

// Helper function to get action badge variant
const getActionVariant = (action: string): 'success' | 'failure' | 'info' | 'process' => {
  const lowerAction = action.toLowerCase();
  if (lowerAction.includes('create') || lowerAction.includes('register')) return 'success';
  if (lowerAction.includes('update') || lowerAction.includes('version_update') || lowerAction.includes('login')) return 'info';
  if (lowerAction.includes('delete') || lowerAction.includes('deregister')) return 'failure';
  if (lowerAction.includes('read') || lowerAction.includes('get') || lowerAction.includes('status_change')) return 'process';
  return 'info';
};

// Helper function to get method badge variant
const getMethodVariant = (method: string | null): 'success' | 'failure' | 'info' | 'process' => {
  if (!method) return 'info';
  const upperMethod = method.toUpperCase();
  if (upperMethod === 'GET') return 'success';
  if (upperMethod === 'POST') return 'info';
  if (upperMethod === 'PUT' || upperMethod === 'PATCH') return 'process';
  if (upperMethod === 'DELETE') return 'failure';
  return 'info';
};

// Helper function to get status badge color based on response status
const getStatusColor = (status: number | null): string => {
  if (!status) return 'text-[#6b7280]';
  if (status >= 200 && status < 300) return 'text-[#10b981]';
  if (status >= 300 && status < 400) return 'text-[#f59e0b]';
  if (status >= 400) return 'text-[#ef4444]';
  return 'text-[#6b7280]';
};

const AuditLogs = (): ReactElement => {
  const { primaryColor } = useAppTheme();
  const roles = useAppSelector((state) => state.auth.roles);
  const tenantId = useAppSelector((state) => state.auth.tenantId);
  const isTenantAdmin = roles?.includes('tenant_admin');
  
  const [auditLogs, setAuditLogs] = useState<AuditLog[]>([]);
  const [resourceTypes, setResourceTypes] = useState<{ value: string; label: string }[]>([]);
  const [modules, setModules] = useState<{ value: string; label: string }[]>([]);
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [error, setError] = useState<string | null>(null);

  // Pagination state
  const [currentPage, setCurrentPage] = useState<number>(1);
  const [limit, setLimit] = useState<number>(10);
  const [pagination, setPagination] = useState<{
    page: number;
    limit: number;
    total: number;
    totalPages: number;
    hasMore: boolean;
  }>({
    page: 1,
    limit: 10,
    total: 0,
    totalPages: 1,
    hasMore: false,
  });

  // Filter state
  const [methodFilter, setMethodFilter] = useState<string | null>(null);
  const [actionFilter, setActionFilter] = useState<string | null>(null);
  const [resourceTypeFilter, setResourceTypeFilter] = useState<string | null>(null);
  const [moduleIdFilter, setModuleIdFilter] = useState<string | null>(null); // New module_id filter
  const [startDate, setStartDate] = useState<string>('');
  const [endDate, setEndDate] = useState<string>('');
  const [orderBy, setOrderBy] = useState<string[] | null>(null);
  const [search, setSearch] = useState<string>('');
  const [debouncedSearch, setDebouncedSearch] = useState<string>('');

  // View modal
  const [viewModalOpen, setViewModalOpen] = useState<boolean>(false);
  const [selectedAuditLogId, setSelectedAuditLogId] = useState<string | null>(null);

  const fetchResourceTypes = async (): Promise<void> => {
    try {
      const response = await auditLogService.getResourceTypesDropdown(tenantId as string | undefined);
      if (response.success) {
        const options = response.data.map((rt: any) => ({
          value: rt.value,
          label: rt.label
        }));
        setResourceTypes(options);
      }
    } catch (err) {
      console.error('Failed to load resource types', err);
    }
  };

  const fetchModules = async (): Promise<void> => {
    try {
      const response = await moduleService.getMyModules(tenantId as string | undefined);
      if (response.success) {
        const options = response.data.map((m: any) => ({
          value: m.id,
          label: m.name
        }));
        setModules(options);
      }
    } catch (err) {
      console.error('Failed to load modules', err);
    }
  };

  const fetchAuditLogs = async (): Promise<void> => {
    try {
      setIsLoading(true);
      setError(null);
      
      let response;
      if (isTenantAdmin) {
        response = await auditLogService.getAll(
          currentPage, 
          limit, 
          {
            method: methodFilter,
            action: actionFilter,
            resource_type: resourceTypeFilter,
            module_id: moduleIdFilter, // Pass module_id filter
            startDate: startDate || null,
            endDate: endDate || null,
            tenant_id: tenantId as string | null,
            search: debouncedSearch || null
          }, 
          orderBy
        );
      } else {
        response = await auditLogService.getMyLogs(currentPage, limit, moduleIdFilter, debouncedSearch || null);
      }

      if (response.success) {
        setAuditLogs(response.data);
        setPagination(response.pagination);
      } else {
        setError('Failed to load audit logs');
      }
    } catch (err: any) {
      setError(err?.response?.data?.error?.message || 'Failed to load audit logs');
    } finally {
      setIsLoading(false);
    }
  };

  // Fetch resource types and modules on mount
  useEffect(() => {
    fetchResourceTypes();
    fetchModules();
  }, [tenantId]);

  // Debouncing for Search
  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedSearch(search);
      setCurrentPage(1);
    }, 500);
    return () => clearTimeout(timer);
  }, [search]);

  // Fetch audit logs on mount and when pagination/filters change
  useEffect(() => {
    fetchAuditLogs();
  }, [currentPage, limit, methodFilter, actionFilter, resourceTypeFilter, moduleIdFilter, startDate, endDate, orderBy, tenantId, debouncedSearch]);

  // View audit log handler
  const handleViewAuditLog = (auditLogId: string): void => {
    setSelectedAuditLogId(auditLogId);
    setViewModalOpen(true);
  };

  // Export handler
  const handleExport = async (): Promise<void> => {
    try {
      const response = await auditLogService.export({
        format: 'json',
        startDate: startDate || undefined,
        endDate: endDate || undefined,
        tenantId: tenantId || undefined
      });
      
      if (response.success) {
        // In a real app, we'd trigger a file download here. 
        // For now, we'll just log and show a message since the response is JSON.
        console.log('Export data:', response.data.records);
        const blob = new Blob([JSON.stringify(response.data.records, null, 2)], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = `audit-logs-${new Date().toISOString().split('T')[0]}.json`;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      }
    } catch (err: any) {
      alert('Failed to export audit logs: ' + (err.message || 'Unknown error'));
    }
  };

  // Load audit log for view
  const loadAuditLog = async (id: string): Promise<AuditLog> => {
    const response = await auditLogService.getById(id);
    return response.data;
  };

  // Define table columns
  const columns: Column<AuditLog>[] = [
    {
      key: 'created_at',
      label: 'Timestamp',
      render: (log) => (
        <span className="text-sm font-normal text-[#0f1724] whitespace-nowrap">{formatDate(log.created_at)}</span>
      ),
      mobileLabel: 'Time',
    },
    {
      key: 'resource_type',
      label: 'Resource Type',
      render: (log) => (
        <span className="text-sm font-normal text-[#0f1724]">{log.resource_type}</span>
      ),
    },
    {
      key: 'module',
      label: 'Module',
      render: (log) => (
        <span className="text-sm font-normal text-[#475569]">
          {log.module?.name || 'Platform'}
        </span>
      ),
    },
    {
      key: 'action',
      label: 'Action',
      render: (log) => (
        <StatusBadge variant={getActionVariant(log.action)}>
          {log.action}
        </StatusBadge>
      ),
    },
    ...(isTenantAdmin ? [{
      key: 'user',
      label: 'User',
      render: (log: AuditLog) => (
        <span className="text-sm font-normal text-[#0f1724]">
          {log.user ? `${log.user.first_name} ${log.user.last_name}` : (log.user_email || 'N/A')}
        </span>
      ),
    }] : []),
    {
      key: 'request_method',
      label: 'Method',
      render: (log) => (
        <StatusBadge variant={getMethodVariant(log.request_method)}>
          {log.request_method ? log.request_method.toUpperCase() : 'N/A'}
        </StatusBadge>
      ),
    },
    {
      key: 'response_status',
      label: 'Status',
      render: (log) => (
        <span className={`text-sm font-normal ${getStatusColor(log.response_status)}`}>
          {log.response_status || 'N/A'}
        </span>
      ),
    },
    {
      key: 'ip_address',
      label: 'IP Address',
      render: (log) => (
        <span className="text-sm font-normal text-[#0f1724] font-mono">
          {log.ip_address || 'N/A'}
        </span>
      ),
    },
    {
      key: 'actions',
      label: 'Actions',
      align: 'right',
      render: (log) => (
        <div className="flex justify-end">
          <button
            type="button"
            onClick={() => handleViewAuditLog(log.id)}
            className="text-sm font-medium transition-colors hover:opacity-80"
            style={{ color: primaryColor }}
          >
            View
          </button>
        </div>
      ),
    },
  ];

  // Mobile card renderer
  const mobileCardRenderer = (log: AuditLog) => (
    <div className="p-4">
      <div className="flex items-start justify-between gap-3 mb-3">
        <div className="flex-1 min-w-0">
          <h3 className="text-sm font-medium text-[#0f1724] truncate">{log.resource_type}</h3>
          <div className="mt-1">
            <StatusBadge variant={getActionVariant(log.action)}>
              {log.action}
            </StatusBadge>
          </div>
        </div>
        <button
          type="button"
          onClick={() => handleViewAuditLog(log.id)}
          className="text-sm font-medium transition-colors shrink-0 hover:opacity-80"
          style={{ color: primaryColor }}
        >
          View
        </button>
      </div>
      <div className="grid grid-cols-2 gap-3 text-xs">
        <div>
          <span className="text-[#9aa6b2]">Timestamp:</span>
          <p className="text-[#0f1724] font-normal mt-1">{formatDate(log.created_at)}</p>
        </div>
        <div>
          <span className="text-[#9aa6b2]">Module:</span>
          <p className="text-[#0f1724] font-normal mt-1">{log.module?.name || 'Platform'}</p>
        </div>
        <div>
          <span className="text-[#9aa6b2]">User:</span>
          <p className="text-[#0f1724] font-normal mt-1">
            {log.user ? `${log.user.first_name} ${log.user.last_name}` : (log.user_email || 'N/A')}
          </p>
        </div>
        <div>
          <span className="text-[#9aa6b2]">Method:</span>
          <div className="mt-1">
            <StatusBadge variant={getMethodVariant(log.request_method)}>
              {log.request_method ? log.request_method.toUpperCase() : 'N/A'}
            </StatusBadge>
          </div>
        </div>
        <div>
          <span className="text-[#9aa6b2]">Status:</span>
          <p className={`font-normal mt-1 ${getStatusColor(log.response_status)}`}>
            {log.response_status || 'N/A'}
          </p>
        </div>
      </div>
    </div>
  );

  return (
    <Layout
      currentPage="Audit Logs"
      pageHeader={{
        title: isTenantAdmin ? 'System Audit Logs' : 'My Activity',
        description: isTenantAdmin 
          ? 'Monitor all activities and changes across the quality platform.' 
          : 'View a chronological history of your own actions on the platform.',
      }}
    >
      {/* Table Container */}
      <div className="bg-white border border-[rgba(0,0,0,0.08)] rounded-lg shadow-[0px_4px_24px_0px_rgba(0,0,0,0.02)] overflow-hidden">
        {/* Table Header with Filters */}
        <div className="border-b border-[rgba(0,0,0,0.08)] px-4 md:px-5 py-3 flex flex-col gap-4">
          <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3">
            {/* Search and Filters */}
            <div className="flex flex-wrap items-center gap-3">
              {/* Global Search */}
              <div className="relative w-full md:w-64">
                <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[#94a3b8]" />
                <input
                  type="text"
                  placeholder="Search logs & metadata..."
                  value={search}
                  onChange={(e) => setSearch(e.target.value)}
                  className="w-full pl-9 pr-4 py-2 border border-[rgba(0,0,0,0.08)] rounded-md text-sm focus:outline-none focus:ring-2 transition-all bg-gray-50/30"
                  onFocus={(e) => {
                    e.currentTarget.style.borderColor = primaryColor;
                    e.currentTarget.style.boxShadow = `0 0 0 2px ${primaryColor}1A`;
                  }}
                  onBlur={(e) => {
                    e.currentTarget.style.borderColor = 'rgba(0,0,0,0.08)';
                    e.currentTarget.style.boxShadow = 'none';
                  }}
                />
              </div>

              {isTenantAdmin && (
                <>
                  {/* Action Filter */}
                  <FilterDropdown
                    label="Action"
                    options={[
                      { value: 'LOGIN', label: 'LOGIN' },
                      { value: 'CREATE', label: 'CREATE' },
                      { value: 'UPDATE', label: 'UPDATE' },
                      { value: 'DELETE', label: 'DELETE' },
                      { value: 'SUBMIT', label: 'SUBMIT' },
                      { value: 'APPROVE', label: 'APPROVE' },
                      { value: 'REJECT', label: 'REJECT' },
                    ]}
                    value={actionFilter}
                    onChange={(value) => {
                      setActionFilter(value as string | null);
                      setCurrentPage(1);
                    }}
                    placeholder="All Actions"
                  />

                  {/* Resource Type Filter */}
                  <FilterDropdown
                    label="Resource Type"
                    options={resourceTypes}
                    value={resourceTypeFilter}
                    onChange={(value) => {
                      setResourceTypeFilter(value as string | null);
                      setCurrentPage(1);
                    }}
                    placeholder="All Resources"
                    isSearchable
                  />
                </>
              )}

              {/* Module Filter */}
              <FilterDropdown
                label="Module"
                options={modules}
                value={moduleIdFilter}
                onChange={(value) => {
                  setModuleIdFilter(value as string | null);
                  setCurrentPage(1);
                }}
                placeholder="All Modules"
              />

              {/* Sort Filter - Always show as it's useful for everyone */}
              <FilterDropdown
                label="Sort by"
                options={[
                  { value: ['created_at', 'desc'], label: 'Newest First' },
                  { value: ['created_at', 'asc'], label: 'Oldest First' },
                  { value: ['action', 'asc'], label: 'Action (A-Z)' },
                  { value: ['resource_type', 'asc'], label: 'Resource Type (A-Z)' },
                ]}
                value={orderBy}
                onChange={(value) => {
                  setOrderBy(value as string[] | null);
                  setCurrentPage(1);
                }}
                placeholder="Newest"
                showIcon
                icon={<ArrowUpDown className="w-3.5 h-3.5 text-[#475569]" />}
              />
            </div>

            {/* Actions */}
            <div className="flex items-center gap-2">
              {isTenantAdmin && (
                <PrimaryButton
                  onClick={handleExport}
                  size="small"
                  className="flex items-center gap-1.5"
                >
                  <Download className="w-3.5 h-3.5" />
                  <span>Export</span>
                </PrimaryButton>
              )}
            </div>
          </div>

          {/* Date Filters - Separated row for better spacing */}
          <div className="flex flex-wrap items-center gap-3 md:gap-6 pt-1">
            <div className="flex items-center gap-2">
              <span className="text-xs font-medium text-[#475569]">From:</span>
              <input 
                type="date" 
                value={startDate}
                onChange={(e) => {
                  setStartDate(e.target.value);
                  setCurrentPage(1);
                }}
                className="text-xs px-2 py-1.5 border border-[rgba(0,0,0,0.08)] rounded focus:outline-none focus:ring-1 focus:ring-[#112868]/20"
              />
            </div>
            <div className="flex items-center gap-2">
              <span className="text-xs font-medium text-[#475569]">To:</span>
              <input 
                type="date"
                value={endDate}
                onChange={(e) => {
                  setEndDate(e.target.value);
                  setCurrentPage(1);
                }}
                className="text-xs px-2 py-1.5 border border-[rgba(0,0,0,0.08)] rounded focus:outline-none focus:ring-1 focus:ring-[#112868]/20"
              />
            </div>
            {(startDate || endDate || actionFilter || resourceTypeFilter || methodFilter || moduleIdFilter || search) && (
              <button 
                onClick={() => {
                  setStartDate('');
                  setEndDate('');
                  setActionFilter(null);
                  setResourceTypeFilter(null);
                  setMethodFilter(null);
                  setModuleIdFilter(null);
                  setSearch('');
                  setCurrentPage(1);
                }}
                className="text-xs hover:underline decoration-offset-2"
                style={{ color: primaryColor }}
              >
                Clear all filters
              </button>
            )}
          </div>
        </div>

        {/* Table */}
        <DataTable
          columns={columns}
          data={auditLogs}
          keyExtractor={(log) => log.id}
          isLoading={isLoading}
          error={error}
          mobileCardRenderer={mobileCardRenderer}
          emptyMessage={isTenantAdmin ? "No audit logs found matching your criteria" : "No activity recorded for your account yet"}
        />

        {/* Pagination */}
        {pagination.total > 0 && (
          <div className="border-t border-[rgba(0,0,0,0.08)] px-4 md:px-5 py-3">
            <Pagination
              currentPage={pagination.page}
              totalPages={pagination.totalPages}
              totalItems={pagination.total}
              limit={limit}
              onPageChange={(page: number) => setCurrentPage(page)}
              onLimitChange={(newLimit: number) => {
                setLimit(newLimit);
                setCurrentPage(1);
              }}
            />
          </div>
        )}
      </div>

      {/* View Audit Log Modal */}
      <ViewAuditLogModal
        isOpen={viewModalOpen}
        onClose={() => {
          setViewModalOpen(false);
          setSelectedAuditLogId(null);
        }}
        auditLogId={selectedAuditLogId}
        onLoadAuditLog={loadAuditLog}
      />
    </Layout>
  );
};

export default AuditLogs;
