import React, { createContext, useContext, useEffect, useReducer, ReactNode } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { MaintenanceCall, Status, Priority, Category, generateId, StatusUpdate } from './types';

const STORAGE_KEY = '@manutencao_chamados';

interface CallsState {
  calls: MaintenanceCall[];
  isLoading: boolean;
}

type CallsAction =
  | { type: 'SET_CALLS'; payload: MaintenanceCall[] }
  | { type: 'ADD_CALL'; payload: MaintenanceCall }
  | { type: 'UPDATE_CALL'; payload: MaintenanceCall }
  | { type: 'SET_LOADING'; payload: boolean };

const initialState: CallsState = {
  calls: [],
  isLoading: true,
};

function callsReducer(state: CallsState, action: CallsAction): CallsState {
  switch (action.type) {
    case 'SET_CALLS':
      return { ...state, calls: action.payload, isLoading: false };
    case 'ADD_CALL':
      return { ...state, calls: [action.payload, ...state.calls] };
    case 'UPDATE_CALL':
      return {
        ...state,
        calls: state.calls.map(call =>
          call.id === action.payload.id ? action.payload : call
        ),
      };
    case 'SET_LOADING':
      return { ...state, isLoading: action.payload };
    default:
      return state;
  }
}

interface CallsContextValue {
  calls: MaintenanceCall[];
  isLoading: boolean;
  addCall: (unit: string, category: Category, description: string) => Promise<MaintenanceCall>;
  updateStatus: (callId: string, status: Status, comment?: string) => Promise<void>;
  updatePriority: (callId: string, priority: Priority) => Promise<void>;
  getCallById: (callId: string) => MaintenanceCall | undefined;
  getPendingCalls: () => MaintenanceCall[];
  getCompletedCalls: () => MaintenanceCall[];
}

const CallsContext = createContext<CallsContextValue | null>(null);

export function CallsProvider({ children }: { children: ReactNode }) {
  const [state, dispatch] = useReducer(callsReducer, initialState);

  // Carregar chamados do AsyncStorage
  useEffect(() => {
    loadCalls();
  }, []);

  // Salvar chamados quando mudam
  useEffect(() => {
    if (!state.isLoading) {
      saveCalls(state.calls);
    }
  }, [state.calls, state.isLoading]);

  async function loadCalls() {
    try {
      const stored = await AsyncStorage.getItem(STORAGE_KEY);
      if (stored) {
        const calls = JSON.parse(stored) as MaintenanceCall[];
        dispatch({ type: 'SET_CALLS', payload: calls });
      } else {
        dispatch({ type: 'SET_LOADING', payload: false });
      }
    } catch (error) {
      console.error('Erro ao carregar chamados:', error);
      dispatch({ type: 'SET_LOADING', payload: false });
    }
  }

  async function saveCalls(calls: MaintenanceCall[]) {
    try {
      await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(calls));
    } catch (error) {
      console.error('Erro ao salvar chamados:', error);
    }
  }

  async function addCall(
    unit: string,
    category: Category,
    description: string
  ): Promise<MaintenanceCall> {
    const now = Date.now();
    const newCall: MaintenanceCall = {
      id: generateId(),
      unit,
      category,
      description,
      priority: 'media',
      status: 'aberto',
      createdAt: now,
      updatedAt: now,
      history: [
        {
          id: generateId(),
          status: 'aberto',
          comment: 'Chamado aberto',
          timestamp: now,
        },
      ],
    };
    dispatch({ type: 'ADD_CALL', payload: newCall });
    return newCall;
  }

  async function updateStatus(callId: string, status: Status, comment?: string) {
    const call = state.calls.find(c => c.id === callId);
    if (!call) return;

    const now = Date.now();
    const statusUpdate: StatusUpdate = {
      id: generateId(),
      status,
      comment,
      timestamp: now,
    };

    const updatedCall: MaintenanceCall = {
      ...call,
      status,
      updatedAt: now,
      history: [...call.history, statusUpdate],
    };

    dispatch({ type: 'UPDATE_CALL', payload: updatedCall });
  }

  async function updatePriority(callId: string, priority: Priority) {
    const call = state.calls.find(c => c.id === callId);
    if (!call) return;

    const updatedCall: MaintenanceCall = {
      ...call,
      priority,
      updatedAt: Date.now(),
    };

    dispatch({ type: 'UPDATE_CALL', payload: updatedCall });
  }

  function getCallById(callId: string): MaintenanceCall | undefined {
    return state.calls.find(c => c.id === callId);
  }

  function getPendingCalls(): MaintenanceCall[] {
    return state.calls.filter(c => c.status !== 'concluido' && c.status !== 'cancelado');
  }

  function getCompletedCalls(): MaintenanceCall[] {
    return state.calls.filter(c => c.status === 'concluido' || c.status === 'cancelado');
  }

  const value: CallsContextValue = {
    calls: state.calls,
    isLoading: state.isLoading,
    addCall,
    updateStatus,
    updatePriority,
    getCallById,
    getPendingCalls,
    getCompletedCalls,
  };

  return <CallsContext.Provider value={value}>{children}</CallsContext.Provider>;
}

export function useCalls(): CallsContextValue {
  const context = useContext(CallsContext);
  if (!context) {
    throw new Error('useCalls deve ser usado dentro de CallsProvider');
  }
  return context;
}
