import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import Helpers from '@/utilities/Helpers';
import { createAsyncThunk, createSlice, Draft, PayloadAction } from '@reduxjs/toolkit';
import { message } from 'antd';
import axios, { AxiosResponse } from 'axios';
import { DataMigrationActions } from './actionTypes';
import {
  uploadLegacyDump,
  getImportStatus,
  getAnalysis,
  startMigration as startMigrationApi,
  getMigrationStatus,
  getReconciliationReport,
  cleanupMigration,
} from '@/services/api/dataMigration';

export interface AnalysisSummary {
  total_staff: number;
  active_staff: number;
  inactive_staff: number;
  branches: number;
  positions: number;
  salary_grades: number;
  salary_notches: number;
  payroll_months: number;
  attendance_records: number;
  attendance_date_range: [string | null, string | null];
  leave_requests: number;
  loans: number;
  allowance_types: number;
  deduction_types: number;
  dependents: number;
  guarantors: number;
  qualifications: number;
  work_experiences: number;
  holidays: number;
}

export interface DataQuality {
  staff_without_email: number;
  staff_with_duplicate_email: number;
  staff_with_no_branch: number;
  staff_with_no_position: number;
  staff_with_no_salary_grade: number;
  orphaned_payroll_records: number;
  orphaned_attendance_records: number;
  unresolvable_allowance_targets: number;
  unresolvable_deduction_targets: number;
}

export interface AnalysisResult {
  schema?: {
    tables_found: string[];
    tables_missing: string[];
    columns: Record<string, string[]>;
  };
  summary: AnalysisSummary;
  data_quality: DataQuality;
  warnings: string[];
  estimates: {
    total_records_to_migrate: number;
    estimated_duration_minutes: number;
  };
}

export interface PhaseSummary {
  phase: number;
  label: string;
  created: number;
  failed: number;
  skipped: number;
}

export interface MigrationStatus {
  phase: number;
  phaseLabel: string;
  progress: number;
  startedAt?: string;
  completedAt?: string;
  error?: string;
  phaseSummaries: PhaseSummary[];
  errors?: Array<{ phase: number; entity: string; old_id: string; error: string }>;
}

export interface Comparison {
  entity: string;
  old: number;
  new: number;
  match: boolean;
  note?: string;
}

export interface PayrollReconciliation {
  period: string;
  old_net_total: number;
  new_net_total: number;
  match: boolean;
}

export interface ReconciliationReport {
  comparisons: Comparison[];
  payroll_reconciliation: PayrollReconciliation[];
  failures: Array<{ phase: number; entity: string; old_id: string; error: string }>;
  unmapped_references: Array<{ source: string; field: string; old_value: string; reason: string }>;
  phase_summaries: PhaseSummary[];
}

export interface ImportStatus {
  status: 'none' | 'queued' | 'importing' | 'analyzing' | 'ready' | 'failed';
  message: string;
  updatedAt?: string;
  analysis?: AnalysisResult;
}

interface DataMigrationState {
  uploading: boolean;
  uploadProgress: number;
  importStatus: ImportStatus | null;
  analysis: AnalysisResult | null;
  loadingAnalysis: boolean;
  migrationStatus: MigrationStatus | null;
  loadingStatus: boolean;
  starting: boolean;
  report: ReconciliationReport | null;
  loadingReport: boolean;
  cleaningUp: boolean;
  error: string | null;
}

const initialState: DataMigrationState = {
  uploading: false,
  uploadProgress: 0,
  importStatus: null,
  analysis: null,
  loadingAnalysis: false,
  migrationStatus: null,
  loadingStatus: false,
  starting: false,
  report: null,
  loadingReport: false,
  cleaningUp: false,
  error: null,
};

export const uploadDump = createAsyncThunk(
  DataMigrationActions.UPLOAD,
  async ({ file, onProgress }: { file: File; onProgress?: (percent: number) => void }, { rejectWithValue }) => {
    try {
      const response = await uploadLegacyDump(file, onProgress);
      return response.data as { message: string };
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchImportStatus = createAsyncThunk(
  DataMigrationActions.FETCH_IMPORT_STATUS,
  async () => {
    const response = (await getImportStatus()) as AxiosResponse<ImportStatus>;
    return response.data;
  },
);

export const fetchAnalysis = createAsyncThunk(
  DataMigrationActions.FETCH_ANALYSIS,
  async () => {
    const response = (await getAnalysis()) as AxiosResponse<AnalysisResult>;
    return response.data;
  },
);

export const startMigration = createAsyncThunk(
  DataMigrationActions.START_MIGRATION,
  async (options: { skip_payroll?: boolean; skip_attendance?: boolean; from_date?: string } | undefined, { rejectWithValue }) => {
    try {
      const response = await startMigrationApi(options);
      return response.data as { message: string; tracking_id: string };
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchStatus = createAsyncThunk(
  DataMigrationActions.FETCH_STATUS,
  async () => {
    const response = (await getMigrationStatus()) as AxiosResponse<MigrationStatus>;
    return response.data;
  },
);

export const fetchReport = createAsyncThunk(
  DataMigrationActions.FETCH_REPORT,
  async () => {
    const response = (await getReconciliationReport()) as AxiosResponse<ReconciliationReport>;
    return response.data;
  },
);

export const cleanup = createAsyncThunk(
  DataMigrationActions.CLEANUP,
  async (_, { rejectWithValue }) => {
    try {
      const response = await cleanupMigration();
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const DataMigrationSlice = createSlice({
  name: 'dataMigration',
  initialState,
  reducers: {
    setUploadProgress: (state: Draft<DataMigrationState>, action: PayloadAction<number>) => {
      state.uploadProgress = action.payload;
    },
    resetState: () => initialState,
  },
  extraReducers(builder) {
    builder
      .addCase(uploadDump.pending, (state: Draft<DataMigrationState>) => {
        state.uploading = true;
        state.uploadProgress = 0;
        state.error = null;
        state.importStatus = null;
        state.analysis = null;
      })
      .addCase(uploadDump.fulfilled, (state: Draft<DataMigrationState>) => {
        state.uploading = false;
        state.uploadProgress = 100;
        state.importStatus = { status: 'queued', message: 'Import queued...' };
      })
      .addCase(uploadDump.rejected, (state: Draft<DataMigrationState>, action: RejectedActionPayload) => {
        state.uploading = false;
        state.uploadProgress = 0;
        message.error(Helpers.handleServerError(action.payload), 10);
      })

      .addCase(fetchImportStatus.fulfilled, (state: Draft<DataMigrationState>, action: PayloadAction<ImportStatus>) => {
        state.importStatus = action.payload;
        if (action.payload.status === 'ready' && action.payload.analysis) {
          state.analysis = action.payload.analysis;
        }
        if (action.payload.status === 'failed') {
          state.error = action.payload.message;
        }
      })

      .addCase(fetchAnalysis.pending, (state: Draft<DataMigrationState>) => {
        state.loadingAnalysis = true;
      })
      .addCase(fetchAnalysis.fulfilled, (state: Draft<DataMigrationState>, action: PayloadAction<AnalysisResult>) => {
        state.loadingAnalysis = false;
        state.analysis = action.payload;
      })
      .addCase(fetchAnalysis.rejected, (state: Draft<DataMigrationState>) => {
        state.loadingAnalysis = false;
      })

      .addCase(startMigration.pending, (state: Draft<DataMigrationState>) => {
        state.starting = true;
        state.error = null;
      })
      .addCase(startMigration.fulfilled, (state: Draft<DataMigrationState>) => {
        state.starting = false;
        message.success('Migration started');
      })
      .addCase(startMigration.rejected, (state: Draft<DataMigrationState>, action: RejectedActionPayload) => {
        state.starting = false;
        message.error(Helpers.handleServerError(action.payload), 10);
      })

      .addCase(fetchStatus.pending, (state: Draft<DataMigrationState>) => {
        state.loadingStatus = true;
      })
      .addCase(fetchStatus.fulfilled, (state: Draft<DataMigrationState>, action: PayloadAction<MigrationStatus>) => {
        state.loadingStatus = false;
        state.migrationStatus = action.payload;
      })
      .addCase(fetchStatus.rejected, (state: Draft<DataMigrationState>) => {
        state.loadingStatus = false;
      })

      .addCase(fetchReport.pending, (state: Draft<DataMigrationState>) => {
        state.loadingReport = true;
      })
      .addCase(fetchReport.fulfilled, (state: Draft<DataMigrationState>, action: PayloadAction<ReconciliationReport>) => {
        state.loadingReport = false;
        state.report = action.payload;
      })
      .addCase(fetchReport.rejected, (state: Draft<DataMigrationState>) => {
        state.loadingReport = false;
      })

      .addCase(cleanup.pending, (state: Draft<DataMigrationState>) => {
        state.cleaningUp = true;
      })
      .addCase(cleanup.fulfilled, () => {
        message.success('Cleanup completed');
        return initialState;
      })
      .addCase(cleanup.rejected, (state: Draft<DataMigrationState>, action: RejectedActionPayload) => {
        state.cleaningUp = false;
        message.error(Helpers.handleServerError(action.payload), 10);
      });
  },
});

export const { setUploadProgress, resetState } = DataMigrationSlice.actions;
export default DataMigrationSlice;
