<?php

namespace App\Http\Controllers;

use App\Models\FeeConfig;
use App\Models\Fee;
use App\Models\SocUnit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Log;
use Carbon\Carbon;

class FeeConfigController extends Controller
{
   public function index()
    {
        try {
            // Fetch all FeeConfig records with relationships
            $feeConfigs = FeeConfig::with(['fee', 'society'])->get();

            if ($feeConfigs->isEmpty()) {
                return response()->json([
                    'status' => 'success',
                    'message' => 'No fee configurations found',
                    'data' => [
                        'fee_configs' => []
                    ]
                ], 200);
            }

            // Group FeeConfig records by SocId, Fs_Id, and Start_Date
            $groupedConfigs = [];

            foreach (
                $feeConfigs->groupBy(function ($config) {
                    return $config->SocId . '_' . $config->Fs_Id . '_' . $config->Start_Date;
                }) as $key => $configs
            ) {
                $firstConfig = $configs->first();
                $socId = $firstConfig->SocId;

                // Get all units from all configs in the group
                $allUnits = [];
                $unitsData = json_decode($firstConfig->units, true) ?? [];
                Log::info('Decoded units for FC_Id: ' . $firstConfig->FC_Id, ['units' => $unitsData]);

                // If unitsData is empty, generate units based on SocUnits
                if (empty($unitsData)) {
                    Log::warning('Units JSON is empty for FC_Id: ' . $firstConfig->FC_Id . ', generating units from SocUnits');
                    $socUnits = SocUnit::whereHas('unitType', function ($query) use ($socId) {
                        $query->where('SocId', $socId);
                    })->with('unitType')->get();

                    foreach ($socUnits as $socUnit) {
                        $unitAmount = $firstConfig->Amount;
                        if ($firstConfig->Per_Uni_Type === 'sqrt') {
                            if (!$socUnit->unitType || !$socUnit->unitType->UT_Size) {
                                Log::error('UnitType or UT_Size missing for SocUnit:', ['SU_ID' => $socUnit->SU_ID]);
                                continue;
                            }
                            $unitAmount = $firstConfig->Amount * $socUnit->unitType->UT_Size;
                        }
                        $suId = $socUnit->SU_ID;
                        if (!isset($allUnits[$suId])) {
                            $allUnits[$suId] = [
                                'SU_ID' => (int)$suId,
                                'Amount' => (int)$unitAmount,
                                'created_at' => now()->toIso8601String(),
                                'updated_at' => now()->toIso8601String(),
                            ];
                        }
                    }
                } else {
                    foreach ($unitsData as $unit) {
                        $suId = isset($unit['SU_ID']) ? (int)$unit['SU_ID'] : null;
                        if ($suId && !isset($allUnits[$suId])) {
                            $allUnits[$suId] = [
                                'SU_ID' => $suId,
                                'Amount' => isset($unit['Amount']) ? (int)$unit['Amount'] : 0,
                                'created_at' => $unit['created_at'] ?? now()->toIso8601String(),
                                'updated_at' => $unit['updated_at'] ?? now()->toIso8601String(),
                            ];
                        }
                    }
                }

                // Calculate unit_type_counts for this SocId
                $socUnits = SocUnit::whereHas('unitType', function ($query) use ($socId) {
                    $query->where('SocId', $socId);
                })->with('unitType')->get();

                $unitTypeCounts = $socUnits->groupBy('unitType.UT_Name')->map(function ($group) {
                    return [
                        'UT_Name' => $group->first()->unitType->UT_Name,
                        'UT_Size' => $group->first()->unitType->UT_Size,
                        'Count' => $group->count()
                    ];
                })->values()->toArray();

                $groupedConfigs[] = [
                    'FC_Id' => $firstConfig->FC_Id,
                    'Fs_Id' => $firstConfig->Fs_Id,
                    'SocId' => $firstConfig->SocId,
                    'Start_Date' => $firstConfig->Start_Date,
                    'Due_Date' => $firstConfig->Due_Date,
                    'Status' => $firstConfig->Status,
                    'Amount' => $firstConfig->Amount,
                    'Per_Uni_Type' => $firstConfig->Per_Uni_Type,
                    'Frequency' => $firstConfig->Frequency,
                    'EB_Disc' => $firstConfig->EB_Disc,
                    'EB_Days' => $firstConfig->EB_Days,
                    'Blk_Payment' => $firstConfig->Blk_Payment,
                    'Blk_Units' => $firstConfig->Blk_Units,
                    'Spl_Cate' => $firstConfig->Spl_Cate,
                    'Late_Charges' => $firstConfig->Late_Charges,
                    'Interest_Charges' => $firstConfig->Interest_Charges,
                    'Int_Chg_Unit' => $firstConfig->Int_Chg_Unit,
                    'IncId' => $firstConfig->IncId,
                    'RecId' => $firstConfig->RecId,
                    'units' => array_values($allUnits),
                    'fee' => $firstConfig->fee ? $firstConfig->fee->toArray() : [],
                    'society' => $firstConfig->society ? $firstConfig->society->toArray() : [],
                    'unit_type_counts' => $unitTypeCounts
                ];
            }

            return response()->json([
                'status' => 'success',
                'message' => 'Fee configurations retrieved successfully',
                'data' => [
                    'fee_configs' => $groupedConfigs
                ]
            ], 200);
        } catch (\Exception $e) {
            Log::error('Error retrieving fee configurations:', ['error' => $e->getMessage()]);
            return response()->json([
                'status' => 'error',
                'message' => 'An unexpected error occurred while retrieving fee configurations: ' . $e->getMessage()
            ], 500);
        }
    }



    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'Fs_Id' => 'required|exists:fees_master,Fs_Id',
            'SocId' => 'required|exists:society_master,SocId',
            'Start_Date' => ['required', 'regex:/^\d{2}\/\d{2}\/\d{4}$/', function ($attribute, $value, $fail) {
                try {
                    Carbon::createFromFormat('d/m/Y', $value);
                } catch (\Exception $e) {
                    $fail('The start date must be a valid date in dd/mm/yyyy format.');
                }
            }],
            'Due_Date' => ['nullable', 'regex:/^\d{2}\/\d{2}\/\d{4}$/', function ($attribute, $value, $fail) {
                if ($value) {
                    try {
                        Carbon::createFromFormat('d/m/Y', $value);
                    } catch (\Exception $e) {
                        $fail('The due date must be a valid date in dd/mm/yyyy format.');
                    }
                }
            }],
            'Status' => 'required|string|in:0,1',
            'Amount' => 'required|integer|min:0',
            'Per_Uni_Type' => 'nullable|in:sqrt,unit,lumsum',
            'Frequency' => 'required|string|in:OneTime,Monthly,Annually,On Occurance',
            'EB_Disc' => 'nullable|integer|min:0',
            'EB_Days' => 'nullable|string|max:50',
            'Blk_Payment' => 'nullable|integer|min:0',
            'Blk_Units' => 'nullable|integer|min:0',
            'Spl_Cate' => 'nullable|string|in:0,1',
            'Late_Charges' => 'nullable|integer|min:0',
            'Interest_Charges' => 'nullable|integer|min:0',
            'Int_Chg_Unit' => 'nullable|string|max:10|in:Month,Year,OneDay',
            'IncId' => 'nullable|integer|min:0',
            'RecId' => 'nullable|integer|min:0',
        ], [
            'Fs_Id.required' => 'The fee ID is required.',
            'Fs_Id.exists' => 'The selected fee does not exist.',
            'SocId.required' => 'The society ID is required.',
            'SocId.exists' => 'The selected society does not exist.',
            'Start_Date.required' => 'The start date is required.',
            'Status.required' => 'The status is required.',
            'Status.in' => 'Status must be 0 (inactive) or 1 (active).',
            'Amount.required' => 'The amount is required.',
            'Amount.integer' => 'The amount must be an integer.',
            'Amount.min' => 'The amount must be at least 0.',
            'Per_Uni_Type.in' => 'Per unit type must be sqrt, unit, or lumsum.',
            'Frequency.required' => 'The frequency is required.',
            'Frequency.in' => 'Frequency must be OneTime, Monthly, Annually, or On Occurance.',
            'Spl_Cate.in' => 'Special category must be 0 or 1.',
            'Int_Chg_Unit.in' => 'Interest charge unit must be Month, Year, or OneDay.',
            'IncId.integer' => 'The IncId must be an integer.',
            'IncId.min' => 'The IncId must be at least 0.',
            'RecId.integer' => 'The RecId must be an integer.',
            'RecId.min' => 'The RecId must be at least 0.',
        ]);

        if ($validator->fails()) {
            Log::error('Validation failed in store:', ['errors' => $validator->errors()->toArray()]);
            return response()->json([
                'status' => 'error',
                'message' => 'Validation failed',
                'errors' => $validator->errors()
            ], 422);
        }

        try {
            $data = $validator->validated();

            // Fetch FeeName from fees_master
            $fee = Fee::find($data['Fs_Id']);
            if (!$fee) {
                Log::error('Fee not found for Fs_Id:', ['Fs_Id' => $data['Fs_Id']]);
                return response()->json([
                    'status' => 'error',
                    'message' => 'Invalid fee ID'
                ], 422);
            }

            // Check for existing FeeConfig for OneTime or Annually to prevent duplicates
            if (in_array($data['Frequency'], ['OneTime', 'Annually'])) {
                $existingConfig = FeeConfig::where('Fs_Id', $data['Fs_Id'])
                    ->where('SocId', $data['SocId'])
                    ->exists();
                if ($existingConfig) {
                    Log::error('Fee configuration already exists for this frequency:', [
                        'Fs_Id' => $data['Fs_Id'],
                        'SocId' => $data['SocId'],
                        'Frequency' => $data['Frequency']
                    ]);
                    return response()->json([
                        'status' => 'error',
                        'message' => "A {$data['Frequency']} fee configuration already exists for this fee and society"
                    ], 422);
                }
            }

            // Fetch SocUnits for the given SocId with their UnitType
            $socUnits = SocUnit::whereHas('unitType', function ($query) use ($data) {
                $query->where('SocId', $data['SocId']);
            })->with('unitType')->get();

            if ($socUnits->isEmpty()) {
                Log::error('No SocUnits found for SocId:', ['SocId' => $data['SocId']]);
                return response()->json([
                    'status' => 'error',
                    'message' => 'No society units found for the provided SocId'
                ], 422);
            }

            // Count SocUnits by UT_Name
            $unitTypeCounts = $socUnits->groupBy('unitType.UT_Name')->map(function ($group) {
                return [
                    'UT_Name' => $group->first()->unitType->UT_Name,
                    'UT_Size' => $group->first()->unitType->UT_Size,
                    'Count' => $group->count()
                ];
            })->values()->toArray();

            // Prepare units array for JSON storage
            $units = [];
            $configData = $data;

            foreach ($socUnits as $socUnit) {
                $unitAmount = $data['Amount'];

                // Calculate Amount based on Per_Uni_Type
                if ($data['Per_Uni_Type'] === 'sqrt') {
                    if (!$socUnit->unitType || !$socUnit->unitType->UT_Size) {
                        Log::error('UnitType or UT_Size missing for SocUnit:', ['SU_ID' => $socUnit->SU_ID]);
                        continue;
                    }
                    $unitAmount = $data['Amount'] * $socUnit->unitType->UT_Size;
                }

                // Check for existing configuration for this SocId, Fs_Id, and Start_Date
                $existingConfig = FeeConfig::where('Fs_Id', $data['Fs_Id'])
                    ->where('SocId', $data['SocId'])
                    ->where('Start_Date', Carbon::createFromFormat('d/m/Y', $data['Start_Date']))
                    ->exists();

                if ($existingConfig) {
                    Log::info('Fee configuration already exists, skipping creation:', [
                        'Fs_Id' => $data['Fs_Id'],
                        'SocId' => $data['SocId'],
                        'Start_Date' => $data['Start_Date']
                    ]);
                    return response()->json([
                        'status' => 'error',
                        'message' => 'Fee configuration already exists for this society and start date'
                    ], 422);
                }

                $units[] = [
                    'SU_ID' => $socUnit->SU_ID,
                    'Amount' => $unitAmount,
                    'created_at' => now()->toIso8601String(),
                    'updated_at' => now()->toIso8601String(),
                ];

                Log::info('Prepared fee configuration for SocUnit:', [
                    'SU_ID' => $socUnit->SU_ID,
                    'Fs_Id' => $data['Fs_Id'],
                    'SocId' => $data['SocId'],
                    'Amount' => $unitAmount,
                    'UT_Name' => $socUnit->unitType->UT_Name,
                    'UT_Size' => $socUnit->unitType->UT_Size,
                    'IncId' => $data['IncId'] ?? null,
                    'RecId' => $data['RecId'] ?? null
                ]);
            }

            if (empty($units)) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'No valid units found for fee configuration'
                ], 422);
            }

            // Calculate Blk_Payment
            if (!empty($configData['Blk_Units']) && $configData['Blk_Units'] > 0) {
                // Use the base Amount for Blk_Payment calculation
                $configData['Blk_Payment'] = $data['Amount'] * $configData['Blk_Units'];
                if (!empty($configData['EB_Disc']) && !empty($configData['EB_Days'])) {
                    $configData['Blk_Payment'] -= $configData['EB_Disc'] * $configData['Blk_Units'];
                }
            }

            // Prepare config data
            $configData['units'] = json_encode($units);
            $configData['IncId'] = isset($configData['IncId']) ? $configData['IncId'] : null;
            $configData['RecId'] = isset($configData['RecId']) ? $configData['RecId'] : null;

            // Create single FeeConfig record
            $feeConfig = FeeConfig::create($configData);
            $feeConfig->load(['fee', 'society']);

            // Prepare response
            $groupedConfig = [
                'FC_Id' => $feeConfig->FC_Id,
                'Fs_Id' => $data['Fs_Id'],
                'SocId' => $data['SocId'],
                'Start_Date' => $data['Start_Date'],
                'Due_Date' => $data['Due_Date'] ?? null,
                'Status' => $data['Status'],
                'Per_Uni_Type' => $data['Per_Uni_Type'],
                'Frequency' => $data['Frequency'],
                'EB_Disc' => $data['EB_Disc'],
                'EB_Days' => $data['EB_Days'],
                'Blk_Payment' => $data['Blk_Payment'],
                'Blk_Units' => $data['Blk_Units'],
                'Spl_Cate' => $data['Spl_Cate'],
                'Late_Charges' => $data['Late_Charges'],
                'Interest_Charges' => $data['Interest_Charges'],
                'Int_Chg_Unit' => $data['Int_Chg_Unit'],
                'IncId' => $data['IncId'] ?? null,
                'RecId' => $data['RecId'] ?? null,
                'units' => $units,
                'fee' => $feeConfig->fee ? $feeConfig->fee->toArray() : [],
                'society' => $feeConfig->society ? $feeConfig->society->toArray() : [],
            ];

            return response()->json([
                'status' => 'success',
                'message' => 'Fee configuration created successfully for all society units',
                'data' => [
                    'fee_config' => $groupedConfig,
                    'unit_type_counts' => $unitTypeCounts
                ]
            ], 201);
        } catch (\Exception $e) {
            Log::error('Error creating fee configuration:', ['error' => $e->getMessage()]);
            return response()->json([
                'status' => 'error',
                'message' => 'An unexpected error occurred while creating the fee configuration: ' . $e->getMessage()
            ], 500);
        }
    }

  public function show($id)
    {
        try {
            // Fetch FeeConfig record for the given FC_Id with related records
            $feeConfig = FeeConfig::with(['fee', 'society'])->find($id);

            if (!$feeConfig) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Fee configuration not found'
                ], 404);
            }

            $socId = $feeConfig->SocId;

            // Calculate unit_type_counts for this SocId
            $socUnits = SocUnit::whereHas('unitType', function ($query) use ($socId) {
                $query->where('SocId', $socId);
            })->with('unitType')->get();

            $unitTypeCounts = $socUnits->groupBy('unitType.UT_Name')->map(function ($group) {
                return [
                    'UT_Name' => $group->first()->unitType->UT_Name,
                    'UT_Size' => $group->first()->unitType->UT_Size,
                    'Count' => $group->count()
                ];
            })->values()->toArray();

            // Decode units JSON
            $unitsData = json_decode($feeConfig->units, true) ?? [];

            // If unitsData is empty, generate units based on SocUnits
            if (empty($unitsData)) {
                Log::warning('Units JSON is empty for FC_Id: ' . $feeConfig->FC_Id . ', generating units from SocUnits');
                $unitsData = [];
                foreach ($socUnits as $socUnit) {
                    $unitAmount = $feeConfig->Amount;
                    if ($feeConfig->Per_Uni_Type === 'sqrt') {
                        if (!$socUnit->unitType || !$socUnit->unitType->UT_Size) {
                            Log::error('UnitType or UT_Size missing for SocUnit:', ['SU_ID' => $socUnit->SU_ID]);
                            continue;
                        }
                        $unitAmount = $feeConfig->Amount * $socUnit->unitType->UT_Size;
                    }
                    $unitsData[] = [
                        'SU_ID' => $socUnit->SU_ID,
                        'Amount' => $unitAmount,
                        'created_at' => now()->toIso8601String(),
                        'updated_at' => now()->toIso8601String(),
                    ];
                }
            }

            // Prepare units array for response
            $units = array_map(function ($unit) {
                return [
                    'SU_ID' => isset($unit['SU_ID']) ? (int)$unit['SU_ID'] : null,
                    'Amount' => isset($unit['Amount']) ? (int)$unit['Amount'] : 0,
                    'created_at' => $unit['created_at'] ?? now()->toIso8601String(),
                    'updated_at' => $unit['updated_at'] ?? now()->toIso8601String(),
                ];
            }, $unitsData);

            // Prepare grouped config
            $groupedConfig = [
                'FC_Id' => $feeConfig->FC_Id,
                'Fs_Id' => $feeConfig->Fs_Id,
                'SocId' => $feeConfig->SocId,
                'Start_Date' => $feeConfig->Start_Date,
                'Due_Date' => $feeConfig->Due_Date,
                'Status' => $feeConfig->Status,
                'Amount' => $feeConfig->Amount,
                'Per_Uni_Type' => $feeConfig->Per_Uni_Type,
                'Frequency' => $feeConfig->Frequency,
                'EB_Disc' => $feeConfig->EB_Disc,
                'EB_Days' => $feeConfig->EB_Days,
                'Blk_Payment' => $feeConfig->Blk_Payment,
                'Blk_Units' => $feeConfig->Blk_Units,
                'Spl_Cate' => $feeConfig->Spl_Cate,
                'Late_Charges' => $feeConfig->Late_Charges,
                'Interest_Charges' => $feeConfig->Interest_Charges,
                'Int_Chg_Unit' => $feeConfig->Int_Chg_Unit,
                'IncId' => $feeConfig->IncId,
                'RecId' => $feeConfig->RecId,
                'units' => $units,
                'fee' => $feeConfig->fee ? $feeConfig->fee->toArray() : [],
                'society' => $feeConfig->society ? $feeConfig->society->toArray() : [],
                'unit_type_counts' => $unitTypeCounts
            ];

            return response()->json([
                'status' => 'success',
                'message' => 'Fee configuration retrieved successfully',
                'data' => [
                    'fee_config' => $groupedConfig
                ]
            ], 200);
        } catch (\Exception $e) {
            Log::error('Error retrieving fee configuration:', ['error' => $e->getMessage()]);
            return response()->json([
                'status' => 'error',
                'message' => 'An unexpected error occurred while retrieving the fee configuration: ' . $e->getMessage()
            ], 500);
        }
    }

    public function update(Request $request, $id)
    {
        $feeConfigs = FeeConfig::where('FC_Id', $id)
            ->orWhere(function ($query) use ($id) {
                $query->whereExists(function ($subQuery) use ($id) {
                    $subQuery->select('FC_Id')
                        ->from('fees_config as fc2')
                        ->where('fc2.FC_Id', $id)
                        ->whereColumn('fc2.SocId', 'fees_config.SocId')
                        ->whereColumn('fc2.Fs_Id', 'fees_config.Fs_Id')
                        ->whereColumn('fc2.Start_Date', 'fees_config.Start_Date');
                });
            })
            ->get();

        if ($feeConfigs->isEmpty()) {
            return response()->json([
                'status' => 'error',
                'message' => 'Fee configuration not found'
            ], 404);
        }

        $validator = Validator::make($request->all(), [
            'Fs_Id' => 'required|exists:fees_master,Fs_Id',
            'SocId' => 'required|exists:society_master,SocId',
            'Start_Date' => ['required', 'regex:/^\d{2}\/\d{2}\/\d{4}$/', function ($attribute, $value, $fail) {
                try {
                    Carbon::createFromFormat('d/m/Y', $value);
                } catch (\Exception $e) {
                    $fail('The start date must be a valid date in dd/mm/yyyy format.');
                }
            }],
            'Due_Date' => ['nullable', 'regex:/^\d{2}\/\d{2}\/\d{4}$/', function ($attribute, $value, $fail) {
                if ($value) {
                    try {
                        Carbon::createFromFormat('d/m/Y', $value);
                    } catch (\Exception $e) {
                        $fail('The due date must be a valid date in dd/mm/yyyy format.');
                    }
                }
            }],
            'Status' => 'required|string|in:0,1',
            'Amount' => 'required|integer|min:0',
            'Per_Uni_Type' => 'nullable|in:sqrt,unit,lumsum',
            'Frequency' => 'required|string|in:OneTime,Monthly,Annually,On Occurance',
            'EB_Disc' => 'nullable|integer|min:0',
            'EB_Days' => 'nullable|string|max:50',
            'Blk_Payment' => 'nullable|integer|min:0',
            'Blk_Units' => 'nullable|integer|min:0',
            'Spl_Cate' => 'nullable|string|in:0,1',
            'Late_Charges' => 'nullable|integer|min:0',
            'Interest_Charges' => 'nullable|integer|min:0',
            'Int_Chg_Unit' => 'nullable|string|max:10|in:Month,Year,OneDay',
            'IncId' => 'nullable|integer|min:0',
            'RecId' => 'nullable|integer|min:0',
        ], [
            'Fs_Id.required' => 'The fee ID is required.',
            'Fs_Id.exists' => 'The selected fee does not exist.',
            'SocId.required' => 'The society ID is required.',
            'SocId.exists' => 'The selected society does not exist.',
            'Start_Date.required' => 'The start date is required.',
            'Status.required' => 'The status is required.',
            'Status.in' => 'Status must be 0 (inactive) or 1 (active).',
            'Amount.required' => 'The amount is required.',
            'Amount.integer' => 'The amount must be an integer.',
            'Amount.min' => 'The amount must be at least 0.',
            'Per_Uni_Type.in' => 'Per unit type must be sqrt, unit, or lumsum.',
            'Frequency.required' => 'The frequency is required.',
            'Frequency.in' => 'Frequency must be OneTime, Monthly, Annually, or On Occurance.',
            'Spl_Cate.in' => 'Special category must be 0 or 1.',
            'Int_Chg_Unit.in' => 'Interest charge unit must be Month, Year, or OneDay.',
            'IncId.integer' => 'The IncId must be an integer.',
            'IncId.min' => 'The IncId must be at least 0.',
            'RecId.integer' => 'The RecId must be an integer.',
            'RecId.min' => 'The RecId must be at least 0.',
        ]);

        if ($validator->fails()) {
            Log::error('Validation failed in update:', ['errors' => $validator->errors()->toArray()]);
            return response()->json([
                'status' => 'error',
                'message' => 'Validation failed',
                'errors' => $validator->errors()
            ], 422);
        }

        try {
            $data = $validator->validated();

            // Fetch FeeName from fees_master
            $fee = Fee::find($data['Fs_Id']);
            if (!$fee) {
                Log::error('Fee not found for Fs_Id:', ['Fs_Id' => $data['Fs_Id']]);
                return response()->json([
                    'status' => 'error',
                    'message' => 'Invalid fee ID'
                ], 422);
            }

            // Check for existing FeeConfig for OneTime or Annually if Fs_Id or SocId is changing
            if ($feeConfigs->first()->Fs_Id != $data['Fs_Id'] || $feeConfigs->first()->SocId != $data['SocId']) {
                if (in_array($data['Frequency'], ['OneTime', 'Annually'])) {
                    $existingConfig = FeeConfig::where('Fs_Id', $data['Fs_Id'])
                        ->where('SocId', $data['SocId'])
                        ->exists();
                    if ($existingConfig) {
                        Log::error('Fee configuration already exists for this frequency:', [
                            'Fs_Id' => $data['Fs_Id'],
                            'SocId' => $data['SocId'],
                            'Frequency' => $data['Frequency']
                        ]);
                        return response()->json([
                            'status' => 'error',
                            'message' => "A {$data['Frequency']} fee configuration already exists for this fee and society"
                        ], 422);
                    }
                }
            }

            // Fetch SocUnits to recalculate Amounts
            $socUnits = SocUnit::whereHas('unitType', function ($query) use ($data) {
                $query->where('SocId', $data['SocId']);
            })->with('unitType')->get();

            foreach ($feeConfigs as $feeConfig) {
                $socUnit = $socUnits->firstWhere('SU_ID', $feeConfig->SU_ID);
                $configData = $data;

                if ($data['Per_Uni_Type'] === 'sqrt') {
                    if (!$socUnit || !$socUnit->unitType || !$socUnit->unitType->UT_Size) {
                        Log::error('UnitType or UT_Size missing for SocUnit:', ['SU_ID' => $feeConfig->SU_ID]);
                        continue;
                    }
                    $configData['Amount'] = $data['Amount'] * $socUnit->unitType->UT_Size;
                }

                if (!empty($configData['Blk_Units']) && $configData['Blk_Units'] > 0) {
                    $configData['Blk_Payment'] = $configData['Amount'] * $configData['Blk_Units'];
                    if (!empty($configData['EB_Disc']) && !empty($configData['EB_Days'])) {
                        $configData['Blk_Payment'] -= $configData['EB_Disc'] * $configData['Blk_Units'];
                    }
                }

                $feeConfig->update($configData);
            }

            $groupedConfig = [
                'FC_Id' => $feeConfigs->first()->FC_Id,
                'Fs_Id' => $data['Fs_Id'],
                'SocId' => $data['SocId'],
                'Start_Date' => $data['Start_Date'],
                'Due_Date' => $data['Due_Date'] ?? null,
                'Status' => $data['Status'],
                'Per_Uni_Type' => $data['Per_Uni_Type'],
                'Frequency' => $data['Frequency'],
                'EB_Disc' => $data['EB_Disc'],
                'EB_Days' => $data['EB_Days'],
                'Blk_Payment' => $data['Blk_Payment'],
                'Blk_Units' => $data['Blk_Units'],
                'Spl_Cate' => $data['Spl_Cate'],
                'Late_Charges' => $data['Late_Charges'],
                'Interest_Charges' => $data['Interest_Charges'],
                'Int_Chg_Unit' => $data['Int_Chg_Unit'],
                'IncId' => $data['IncId'],
                'RecId' => $data['RecId'],
                'units' => $feeConfigs->map(function ($config) {
                    return [
                        'SU_ID' => $config->SU_ID,
                        'Amount' => $config->Amount,
                        'created_at' => $config->created_at->toIso8601String(),
                        'updated_at' => $config->updated_at->toIso8601String(),
                    ];
                })->toArray(),
                'fee' => $feeConfigs->first()->fee ? $feeConfigs->first()->fee->toArray() : [],
                'society' => $feeConfigs->first()->society ? $feeConfigs->first()->society->toArray() : [],
            ];

            return response()->json([
                'status' => 'success',
                'message' => 'Fee configuration updated successfully',
                'data' => $groupedConfig
            ], 200);
        } catch (\Exception $e) {
            Log::error('Error updating fee configuration:', ['error' => $e->getMessage()]);
            return response()->json([
                'status' => 'error',
                'message' => 'An unexpected error occurred while updating the fee configuration: ' . $e->getMessage()
            ], 500);
        }
    }

    public function destroy($id)
    {
        $feeConfigs = FeeConfig::where('FC_Id', $id)
            ->orWhere(function ($query) use ($id) {
                $query->whereExists(function ($subQuery) use ($id) {
                    $subQuery->select('FC_Id')
                        ->from('fees_config as fc2')
                        ->where('fc2.FC_Id', $id)
                        ->whereColumn('fc2.SocId', 'fees_config.SocId')
                        ->whereColumn('fc2.Fs_Id', 'fees_config.Fs_Id')
                        ->whereColumn('fc2.Start_Date', 'fees_config.Start_Date');
                });
            })
            ->get();

        if ($feeConfigs->isEmpty()) {
            return response()->json([
                'status' => 'error',
                'message' => 'Fee configuration not found'
            ], 404);
        }

        try {
            foreach ($feeConfigs as $feeConfig) {
                $feeConfig->delete();
            }
            return response()->json([
                'status' => 'success',
                'message' => 'Fee configuration deleted successfully'
            ], 200);
        } catch (\Exception $e) {
            Log::error('Error deleting fee configuration:', ['error' => $e->getMessage()]);
            return response()->json([
                'status' => 'error',
                'message' => 'An unexpected error occurred while deleting the fee configuration: ' . $e->getMessage()
            ], 500);
        }
    }

    public function createMonthlyFeeConfigs()
    {
        try {
            // Handle Monthly and Annually frequencies
            $frequencies = ['Monthly', 'Annually'];
            $feeConfigs = FeeConfig::where('Status', '1')
                ->whereIn('Frequency', $frequencies)
                ->with('socUnit.unitType')
                ->get();

            $currentDate = Carbon::now();
            $nextMonth = $currentDate->copy()->addMonth()->startOfMonth();
            $nextMonthFormatted = $nextMonth->format('d/m/Y');
            $nextMonthDueDate = $nextMonth->endOfMonth()->format('d/m/Y');

            $nextYear = $currentDate->copy()->addYear()->startOfYear();
            $nextYearFormatted = $nextYear->format('d/m/Y');
            $nextYearDueDate = $nextYear->endOfYear()->format('d/m/Y');

            $createdConfigs = [];
            $unitTypeCountsBySocId = [];

            foreach ($feeConfigs->groupBy(['SocId', 'Fs_Id']) as $socId => $fsIdGroup) {
                foreach ($fsIdGroup as $configs) {
                    $config = $configs->first();

                    // Determine target date based on frequency
                    $targetStartDate = $config->Frequency === 'Monthly' ? $nextMonthFormatted : $nextYearFormatted;
                    $targetDueDate = $config->Frequency === 'Monthly' ? $nextMonthDueDate : $nextYearDueDate;

                    // Skip if configuration already exists for the target date
                    $existingConfig = FeeConfig::where('Fs_Id', $config->Fs_Id)
                        ->where('SocId', $config->SocId)
                        ->where('Start_Date', Carbon::createFromFormat('d/m/Y', $targetStartDate))
                        ->exists();

                    if ($existingConfig) {
                        Log::info('Fee configuration already exists for target date:', [
                            'Fs_Id' => $config->Fs_Id,
                            'SocId' => $config->SocId,
                            'Start_Date' => $targetStartDate,
                            'Frequency' => $config->Frequency
                        ]);
                        continue;
                    }

                    // Fetch SocUnits for the given SocId
                    $socUnits = SocUnit::whereHas('unitType', function ($query) use ($config) {
                        $query->where('SocId', $config->SocId);
                    })->with('unitType')->get();

                    if ($socUnits->isEmpty()) {
                        Log::info('No SocUnits found for SocId:', ['SocId' => $config->SocId]);
                        continue;
                    }

                    // Count SocUnits by UT_Name
                    if (!isset($unitTypeCountsBySocId[$config->SocId])) {
                        $unitTypeCountsBySocId[$config->SocId] = $socUnits->groupBy('unitType.UT_Name')->map(function ($group) {
                            return [
                                'UT_Name' => $group->first()->unitType->UT_Name,
                                'UT_Size' => $group->first()->unitType->UT_Size,
                                'Count' => $group->count()
                            ];
                        })->values()->toArray();
                    }

                    $virtualFCId = null;

                    foreach ($socUnits as $socUnit) {
                        $newConfig = $config->replicate();
                        $newConfig->Start_Date = $targetStartDate;
                        $newConfig->Due_Date = $targetDueDate;
                        $newConfig->SU_ID = $socUnit->SU_ID;
                        $newConfig->IncId = $config->IncId;
                        $newConfig->RecId = $config->RecId;

                        if ($config->Per_Uni_Type === 'sqrt') {
                            if (!$socUnit->unitType || !$socUnit->unitType->UT_Size) {
                                Log::error('UnitType or UT_Size missing for SocUnit:', ['SU_ID' => $socUnit->SU_ID]);
                                continue;
                            }
                            $newConfig->Amount = $config->Amount * $socUnit->unitType->UT_Size;
                        }

                        if (!empty($newConfig->Blk_Units) && $newConfig->Blk_Units > 0) {
                            $newConfig->Blk_Payment = $newConfig->Amount * $newConfig->Blk_Units;
                            if (!empty($newConfig->EB_Disc) && !empty($newConfig->EB_Days)) {
                                $newConfig->Blk_Payment -= $newConfig->EB_Disc * $newConfig->Blk_Units;
                            }
                        }

                        $newConfig->save();

                        if (!$virtualFCId) {
                            $virtualFCId = $newConfig->FC_Id;
                        }

                        $responseData = $newConfig->toArray();
                        $responseData['Start_Date'] = $newConfig->Start_Date;
                        if ($newConfig->Due_Date) {
                            $responseData['Due_Date'] = $newConfig->Due_Date;
                        }
                        $responseData['FC_Id'] = $virtualFCId;

                        $createdConfigs[] = $responseData;

                        Log::info('Created new fee configuration:', [
                            'Fs_Id' => $newConfig->Fs_Id,
                            'SocId' => $config->SocId,
                            'SU_ID' => $newConfig->SU_ID,
                            'Start_Date' => $targetStartDate,
                            'Due_Date' => $targetDueDate,
                            'Frequency' => $newConfig->Frequency,
                            'Amount' => $newConfig->Amount,
                            'UT_Name' => $socUnit->unitType->UT_Name,
                            'UT_Size' => $socUnit->unitType->UT_Size,
                            'Blk_Payment' => $newConfig->Blk_Payment,
                            'IncId' => $newConfig->IncId,
                            'RecId' => $newConfig->RecId
                        ]);
                    }
                }
            }

            if (empty($createdConfigs)) {
                return response()->json([
                    'status' => 'success',
                    'message' => 'No new fee configurations were created due to existing records or no eligible fees'
                ], 200);
            }

            // Group created configs by SocId, Fs_Id, and Start_Date
            $groupedConfigs = [];
            foreach ($createdConfigs as $config) {
                $key = $config['SocId'] . '_' . $config['Fs_Id'] . '_' . $config['Start_Date'];
                if (!isset($groupedConfigs[$key])) {
                    $groupedConfigs[$key] = [
                        'FC_Id' => $config['FC_Id'],
                        'Fs_Id' => $config['Fs_Id'],
                        'SocId' => $config['SocId'],
                        'Start_Date' => $config['Start_Date'],
                        'Due_Date' => $config['Due_Date'],
                        'Status' => $config['Status'],
                        'Per_Uni_Type' => $config['Per_Uni_Type'],
                        'Frequency' => $config['Frequency'],
                        'EB_Disc' => $config['EB_Disc'],
                        'EB_Days' => $config['EB_Days'],
                        'Blk_Payment' => $config['Blk_Payment'],
                        'Blk_Units' => $config['Blk_Units'],
                        'Spl_Cate' => $config['Spl_Cate'],
                        'Late_Charges' => $config['Late_Charges'],
                        'Interest_Charges' => $config['Interest_Charges'],
                        'Int_Chg_Unit' => $config['Int_Chg_Unit'],
                        'IncId' => $config['IncId'],
                        'RecId' => $config['RecId'],
                        'units' => [],
                        'fee' => $config['fee'] ?? [],
                        'society' => $config['society'] ?? [],
                    ];
                }
                $groupedConfigs[$key]['units'][] = [
                    'SU_ID' => $config['SU_ID'],
                    'Amount' => $config['Amount'],
                    'created_at' => $config['created_at'],
                    'updated_at' => $config['updated_at'],
                ];
            }

            $unitTypeCounts = array_merge(...array_values($unitTypeCountsBySocId));

            return response()->json([
                'status' => 'success',
                'message' => 'Fee configurations created successfully for all society units',
                'data' => [
                    'fee_configs' => array_values($groupedConfigs),
                    'unit_type_counts' => $unitTypeCounts
                ]
            ], 200);
        } catch (\Exception $e) {
            Log::error('Error creating fee configurations:', ['error' => $e->getMessage()]);
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to create fee configurations: ' . $e->getMessage()
            ], 500);
        }
    }
}
