import { createSlice, createAsyncThunk, type PayloadAction } from "@reduxjs/toolkit"

// Define types for the pricing structure
export interface ChargeType {
  id: number
  name: string
  uom: string // Unit of Measure (per hour, per mile, flat, percentage, etc.)
  isDefault: boolean
  description?: string
}

export interface ServiceType {
  id: number
  name: string
  description?: string
  isDefault: boolean
}

export interface VehicleTypePrice {
  id: number
  vehicleTypeId: number
  vehicleTypeName: string
  basePrice: number
  serviceTypeId: number
  cityId?: number | null
  cityName?: string | null
}

export interface AddOnPrice {
  id: number
  addOnId: number
  addOnName: string
  price: number
  vehicleTypeId: number
  vehicleTypeName: string
  cityId?: number | null
  cityName?: string | null
}

export interface ServiceCharge {
  id: number
  chargeTypeId: number
  chargeTypeName: string
  chargeTypeUom: string
  value: number
  serviceTypeId: number
  serviceTypeName: string
  cityId?: number | null
  cityName?: string | null
}

export interface MeetAndGreetPrice {
  id: number
  serviceTypeId: number
  serviceTypeName: string
  price: number
  cityId?: number | null
  cityName?: string | null
}

export interface PaymentPlan {
  id: number
  name: string
  description?: string
  isDefault: boolean
  vehicleTypePrices: VehicleTypePrice[]
  addOnPrices: AddOnPrice[]
  serviceCharges: ServiceCharge[]
  meetAndGreetPrices: MeetAndGreetPrice[]
}

// Define the state type
interface PricingState {
  chargeTypes: {
    items: ChargeType[]
    status: "idle" | "loading" | "succeeded" | "failed"
    error: string | null
  }
  serviceTypes: {
    items: ServiceType[]
    status: "idle" | "loading" | "succeeded" | "failed"
    error: string | null
  }
  paymentPlans: {
    items: PaymentPlan[]
    selectedPlanId: number | null
    status: "idle" | "loading" | "succeeded" | "failed"
    error: string | null
  }
  filters: {
    search: string
    cityId: number | null
    vehicleTypeId: number | null
    serviceTypeId: number | null
  }
}

// Initial state
const initialState: PricingState = {
  chargeTypes: {
    items: [],
    status: "idle",
    error: null,
  },
  serviceTypes: {
    items: [],
    status: "idle",
    error: null,
  },
  paymentPlans: {
    items: [],
    selectedPlanId: null,
    status: "idle",
    error: null,
  },
  filters: {
    search: "",
    cityId: null,
    vehicleTypeId: null,
    serviceTypeId: null,
  },
}

// Sample data for initial development
const sampleChargeTypes: ChargeType[] = [
  { id: 1, name: "Flat Rate", uom: "flat", isDefault: true, description: "A fixed charge regardless of distance or time" },
  { id: 2, name: "Per Hour", uom: "hour", isDefault: true, description: "Charge applied per hour of service" },
  { id: 3, name: "Per Unit", uom: "unit", isDefault: true, description: "Charge applied per unit" },
  { id: 4, name: "OT/Wait Time", uom: "hour", isDefault: true, description: "Overtime or waiting time charges" },
  { id: 5, name: "Extra Stops", uom: "stop", isDefault: true, description: "Charge for additional stops during a trip" },
  { id: 6, name: "Std Grat", uom: "percentage", isDefault: true, description: "Standard gratuity percentage" },
  { id: 7, name: "Extra Grat", uom: "percentage", isDefault: true, description: "Additional gratuity percentage" },
  { id: 8, name: "Fuel Surch", uom: "percentage", isDefault: true, description: "Fuel surcharge percentage" },
  { id: 9, name: "STC Surch", uom: "percentage", isDefault: true },
  { id: 10, name: "Discount", uom: "percentage", isDefault: true, description: "Discount percentage applied to total" },
  { id: 11, name: "Per Mile", uom: "mile", isDefault: true, description: "Charge applied per mile traveled" },
  { id: 12, name: "Per Pass", uom: "passenger", isDefault: true, description: "Charge applied per passenger" },
  { id: 13, name: "Tolls", uom: "flat", isDefault: true, description: "Toll fees for highways and bridges" },
  { id: 14, name: "Parking", uom: "flat", isDefault: true, description: "Parking fees" },
  { id: 15, name: "Setup Fee", uom: "flat", isDefault: true },
  { id: 16, name: "Admin Fee", uom: "flat", isDefault: true, description: "Administrative processing fee" },
  { id: 17, name: "Voucher", uom: "flat", isDefault: true },
  { id: 18, name: "Misc Fee 1", uom: "flat", isDefault: true },
  { id: 19, name: "Misc Fee 2", uom: "flat", isDefault: true },
  { id: 20, name: "Airport Fee", uom: "flat", isDefault: true, description: "Airport access and pickup fees" },
  { id: 21, name: "Holiday Charge", uom: "percentage", isDefault: true, description: "Additional charge for holiday service" },
  { id: 22, name: "Late Early Charge", uom: "flat", isDefault: true, description: "Fee for late night or early morning service" },
]

const sampleServiceTypes: ServiceType[] = [
  { 
    id: 1, 
    name: "Airport Pickup or Drop Off", 
    description: "Airport to/from the city. Trip time is 2 hours only. Beyond that, standard service charges apply.", 
    isDefault: true 
  },
  { 
    id: 2, 
    name: "Point to Point", 
    description: "To or from medical facility or locations", 
    isDefault: true 
  },
  { 
    id: 3, 
    name: "Per Hour", 
    description: "Between Cities - Hours are calculated garage to garage", 
    isDefault: true 
  },
  { 
    id: 4, 
    name: "10 Hours per day", 
    description: "After the 10 hours, the rate will be charged per hour", 
    isDefault: true 
  },
  { 
    id: 5, 
    name: "Tour", 
    description: "Custom tour services", 
    isDefault: true 
  },
]

// Async thunks for API calls
export const fetchChargeTypes = createAsyncThunk(
  "pricing/fetchChargeTypes", 
  async (_, { rejectWithValue }) => {
    try {
      // In a real app, this would be an API call
      await new Promise((resolve) => setTimeout(resolve, 500))
      return sampleChargeTypes
    } catch (error) {
      return rejectWithValue("Failed to fetch charge types")
    }
  }
)

export const addChargeType = createAsyncThunk(
  "pricing/addChargeType",
  async (chargeType: Omit<ChargeType, "id">, { rejectWithValue }) => {
    try {
      // In a real app, this would be an API call
      await new Promise((resolve) => setTimeout(resolve, 500))
      return {
        ...chargeType,
        id: Date.now(),
      }
    } catch (error) {
      return rejectWithValue("Failed to add charge type")
    }
  }
)

export const fetchServiceTypes = createAsyncThunk(
  "pricing/fetchServiceTypes", 
  async (_, { rejectWithValue }) => {
    try {
      // In a real app, this would be an API call
      await new Promise((resolve) => setTimeout(resolve, 500))
      return sampleServiceTypes
    } catch (error) {
      return rejectWithValue("Failed to fetch service types")
    }
  }
)

export const fetchPaymentPlans = createAsyncThunk(
  "pricing/fetchPaymentPlans", 
  async (_, { rejectWithValue }) => {
    try {
      // In a real app, this would be an API call
      await new Promise((resolve) => setTimeout(resolve, 500))
      // Return empty array initially - we'll create plans through the UI
      return []
    } catch (error) {
      return rejectWithValue("Failed to fetch payment plans")
    }
  }
)

export const addPaymentPlan = createAsyncThunk(
  "pricing/addPaymentPlan",
  async (plan: { name: string; description?: string; isDefault: boolean }, { rejectWithValue }) => {
    try {
      // In a real app, this would be an API call
      await new Promise((resolve) => setTimeout(resolve, 500))
      return {
        ...plan,
        id: Date.now(),
        vehicleTypePrices: [],
        addOnPrices: [],
        serviceCharges: [],
        meetAndGreetPrices: [],
      }
    } catch (error) {
      return rejectWithValue("Failed to add payment plan")
    }
  }
)

export const updatePaymentPlan = createAsyncThunk(
  "pricing/updatePaymentPlan",
  async (
    { id, updates }: { id: number; updates: Partial<Omit<PaymentPlan, "id">> },
    { rejectWithValue }
  ) => {
    try {
      // In a real app, this would be an API call
      await new Promise((resolve) => setTimeout(resolve, 500))
      return { id, updates }
    } catch (error) {
      return rejectWithValue("Failed to update payment plan")
    }
  }
)

export const deletePaymentPlan = createAsyncThunk(
  "pricing/deletePaymentPlan",
  async (id: number, { rejectWithValue }) => {
    try {
      // In a real app, this would be an API call
      await new Promise((resolve) => setTimeout(resolve, 500))
      return id
    } catch (error) {
      return rejectWithValue("Failed to delete payment plan")
    }
  }
)

export const addVehicleTypePrice = createAsyncThunk(
  "pricing/addVehicleTypePrice",
  async (
    { 
      planId, 
      price 
    }: { 
      planId: number; 
      price: Omit<VehicleTypePrice, "id">
    },
    { rejectWithValue }
  ) => {
    try {
      // In a real app, this would be an API call
      await new Promise((resolve) => setTimeout(resolve, 500))
      return {
        planId,
        price: {
          ...price,
          id: Date.now(),
        },
      }
    } catch (error) {
      return rejectWithValue("Failed to add vehicle type price")
    }
  }
)

export const addAddOnPrice = createAsyncThunk(
  "pricing/addAddOnPrice",
  async (
    { 
      planId, 
      price 
    }: { 
      planId: number; 
      price: Omit<AddOnPrice, "id">
    },
    { rejectWithValue }
  ) => {
    try {
      // In a real app, this would be an API call
      await new Promise((resolve) => setTimeout(resolve, 500))
      return {
        planId,
        price: {
          ...price,
          id: Date.now(),
        },
      }
    } catch (error) {
      return rejectWithValue("Failed to add add-on price")
    }
  }
)

export const addServiceCharge = createAsyncThunk(
  "pricing/addServiceCharge",
  async (
    { 
      planId, 
      charge 
    }: { 
      planId: number; 
      charge: Omit<ServiceCharge, "id">
    },
    { rejectWithValue }
  ) => {
    try {
      // In a real app, this would be an API call
      await new Promise((resolve) => setTimeout(resolve, 500))
      return {
        planId,
        charge: {
          ...charge,
          id: Date.now(),
        },
      }
    } catch (error) {
      return rejectWithValue("Failed to add service charge")
    }
  }
)

export const addMeetAndGreetPrice = createAsyncThunk(
  "pricing/addMeetAndGreetPrice",
  async (
    { 
      planId, 
      price 
    }: { 
      planId: number; 
      price: Omit<MeetAndGreetPrice, "id">
    },
    { rejectWithValue }
  ) => {
    try {
      // In a real app, this would be an API call
      await new Promise((resolve) => setTimeout(resolve, 500))
      return {
        planId,
        price: {
          ...price,
          id: Date.now(),
        },
      }
    } catch (error) {
      return rejectWithValue("Failed to add meet and greet price")
    }
  }
)

// Create the slice
const pricingSlice = createSlice({
  name: "pricing",
  initialState,
  reducers: {
    updateFilters: (state, action: PayloadAction<Partial<PricingState["filters"]>>) => {
      state.filters = { ...state.filters, ...action.payload }
    },
    resetFilters: (state) => {
      state.filters = initialState.filters
    },
    setSelectedPlan: (state, action: PayloadAction<number | null>) => {
      state.paymentPlans.selectedPlanId = action.payload
    },
  },
  extraReducers: (builder) => {
    builder
      // Charge Types
      .addCase(fetchChargeTypes.pending, (state) => {
        state.chargeTypes.status = "loading"
      })
      .addCase(fetchChargeTypes.fulfilled, (state, action) => {
        state.chargeTypes.status = "succeeded"
        state.chargeTypes.items = action.payload
      })
      .addCase(fetchChargeTypes.rejected, (state, action) => {
        state.chargeTypes.status = "failed"
        state.chargeTypes.error = action.payload as string
      })
      .addCase(addChargeType.fulfilled, (state, action) => {
        state.chargeTypes.items.push(action.payload)
      })

      // Service Types
      .addCase(fetchServiceTypes.pending, (state) => {
        state.serviceTypes.status = "loading"
      })
      .addCase(fetchServiceTypes.fulfilled, (state, action) => {
        state.serviceTypes.status = "succeeded"
        state.serviceTypes.items = action.payload
      })
      .addCase(fetchServiceTypes.rejected, (state, action) => {
        state.serviceTypes.status = "failed"
        state.serviceTypes.error = action.payload as string
      })

      // Payment Plans
      .addCase(fetchPaymentPlans.pending, (state) => {
        state.paymentPlans.status = "loading"
      })
      .addCase(fetchPaymentPlans.fulfilled, (state, action) => {
        state.paymentPlans.status = "succeeded"
        state.paymentPlans.items = action.payload
      })
      .addCase(fetchPaymentPlans.rejected, (state, action) => {
        state.paymentPlans.status = "failed"
        state.paymentPlans.error = action.payload as string
      })
      .addCase(addPaymentPlan.fulfilled, (state, action) => {
        state.paymentPlans.items.push(action.payload)
        // If this is the first plan or it's set as default, select it
        if (state.paymentPlans.items.length === 1 || action.payload.isDefault) {
          state.paymentPlans.selectedPlanId = action.payload.id
        }
      })
      .addCase(updatePaymentPlan.fulfilled, (state, action) => {
        const { id, updates } = action.payload
        const planIndex = state.paymentPlans.items.findIndex((plan) => plan.id === id)
        
        if (planIndex !== -1) {
          state.paymentPlans.items[planIndex] = {
            ...state.paymentPlans.items[planIndex],
            ...updates,
          }
          
          // If this plan is set as default, unset default for all other plans
          if (updates.isDefault) {
            state.paymentPlans.items.forEach((plan, index) => {
              if (index !== planIndex) {
                plan.isDefault = false
              }
            })
          }
        }
      })
      .addCase(deletePaymentPlan.fulfilled, (state, action) => {
        const deletedPlanId = action.payload
        state.paymentPlans.items = state.paymentPlans.items.filter((plan) => plan.id !== deletedPlanId)
        
        // If the selected plan was deleted, select another plan if available
        if (state.paymentPlans.selectedPlanId === deletedPlanId) {
          const defaultPlan = state.paymentPlans.items.find((plan) => plan.isDefault)
          state.paymentPlans.selectedPlanId = defaultPlan 
            ? defaultPlan.id 
            : state.paymentPlans.items.length > 0 
              ? state.paymentPlans.items[0].id 
              : null
        }
      })
      
      // Vehicle Type Prices
      .addCase(addVehicleTypePrice.fulfilled, (state, action) => {
        const { planId, price } = action.payload
        const planIndex = state.paymentPlans.items.findIndex((plan) => plan.id === planId)
        
        if (planIndex !== -1) {
          state.paymentPlans.items[planIndex].vehicleTypePrices.push(price)
        }
      })
      
      // Add-on Prices
      .addCase(addAddOnPrice.fulfilled, (state, action) => {
        const { planId, price } = action.payload
        const planIndex = state.paymentPlans.items.findIndex((plan) => plan.id === planId)
        
        if (planIndex !== -1) {
          state.paymentPlans.items[planIndex].addOnPrices.push(price)
        }
      })
      
      // Service Charges
      .addCase(addServiceCharge.fulfilled, (state, action) => {
        const { planId, charge } = action.payload
        const planIndex = state.paymentPlans.items.findIndex((plan) => plan.id === planId)
        
        if (planIndex !== -1) {
          state.paymentPlans.items[planIndex].serviceCharges.push(charge)
        }
      })
      
      // Meet and Greet Prices
      .addCase(addMeetAndGreetPrice.fulfilled, (state, action) => {
        const { planId, price } = action.payload
        const planIndex = state.paymentPlans.items.findIndex((plan) => plan.id === planId)
        
        if (planIndex !== -1) {
          state.paymentPlans.items[planIndex].meetAndGreetPrices.push(price)
        }
      })
  },
})

export const { updateFilters, resetFilters, setSelectedPlan } = pricingSlice.actions

export default pricingSlice.reducer