<?php

namespace App\Http\Controllers;

use App\Models\ZoneMaster;
use App\Models\OrganisationSetting;
use App\Models\OrgMaster;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Validator;

class ZoneMasterController extends Controller
{

    public function index(Request $request)
    {

        $query = ZoneMaster::query();

        $query->with('organisation');

        if ($request->has('org_id')) {
            if ($request->org_id === 'null' || $request->org_id === '') {
                $query->whereNull('Org_Id');
            } else {
                $query->where('Org_Id', $request->org_id);
            }
        }

        if ($request->has('Zon_Code') && !empty($request->Zon_Code)) {
            $query->where('Zon_Code', 'like', '%' . $request->Zon_Code . '%');
        }

        if ($request->has('zon_name') && !empty($request->zon_name)) {
            $query->where('Zon_Name', 'like', '%' . $request->zon_name . '%');
        }

        if ($request->has('global') && $request->global == 'true') {
            $query->whereNull('Org_Id');
        }

        if ($request->has('search') && !empty($request->search)) {
            $query->search($request->search);
        }

        $sortField = $request->get('sort_by', 'Zon_Id');
        $sortDirection = $request->get('sort_dir', 'desc');

        $allowedSortFields = ['Zon_Id', 'Zon_Code', 'Zon_Name', 'Org_Id', 'created_at', 'updated_at'];
        if (!in_array($sortField, $allowedSortFields)) {
            $sortField = 'Zon_Id';
        }

        $sortDirection = strtolower($sortDirection) === 'asc' ? 'asc' : 'desc';
        $query->orderBy($sortField, $sortDirection);

        $perPage = $request->get('per_page', 15);
        $perPage = min(max(1, $perPage), 100);

        $zones = $query->paginate($perPage);

        $zones->getCollection()->transform(function ($zone) {
            $zone->full_zone = $zone->full_zone;
            $zone->organization_name = $zone->organization_name;
            $zone->is_global = $zone->isGlobal();
            return $zone;
        });

        return response()->json([
            'success' => true,
            'message' => 'Zones retrieved successfully',
            'data' => $zones
        ], Response::HTTP_OK);
    }

public function all(Request $request)
{
    $query = ZoneMaster::with('organisation');

    // Optional Filters
    if ($request->has('org_id')) {
        if ($request->org_id === 'null' || $request->org_id === '') {
            $query->whereNull('Org_Id');
        } else {
            $query->where('Org_Id', $request->org_id);
        }
    }

    if ($request->has('search') && !empty($request->search)) {
        $query->search($request->search);
    }

    // Sorting
    $sortField = $request->get('sort_by', 'Zon_Id');
    $sortDirection = strtolower($request->get('sort_dir', 'desc')) === 'asc' ? 'asc' : 'desc';

    $allowedSortFields = ['Zon_Id', 'Zon_Code', 'Zon_Name', 'Org_Id', 'created_at', 'updated_at'];
    if (!in_array($sortField, $allowedSortFields)) {
        $sortField = 'Zon_Id';
    }

    $zones = $query->orderBy($sortField, $sortDirection)->get();

    // Transform Data
    $zones->transform(function ($zone) {
        $zone->full_zone = $zone->full_zone;
        $zone->organization_name = $zone->organization_name;
        $zone->is_global = $zone->isGlobal();
        return $zone;
    });

    return response()->json([
        'success' => true,
        'message' => 'All zones retrieved successfully',
        'data' => $zones
    ], Response::HTTP_OK);
}


    public function store(Request $request)
    {

        $validator = Validator::make($request->all(), [
            'Zon_Code' => 'nullable|string|max:5',
            'Zon_Name' => 'required|string|max:25',
            'Org_Id' => 'nullable|integer|exists:org_master,Org_Id'
        ], [
            'Zon_Code.required' => 'Zone code is required',
            'Zon_Code.max' => 'Zone code cannot exceed 5 characters',
            'Zon_Name.required' => 'Zone name is required',
            'Zon_Name.max' => 'Zone name cannot exceed 25 characters',
            'Org_Id.exists' => 'The selected organization does not exist'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation failed',
                'errors' => $validator->errors()
            ], Response::HTTP_BAD_REQUEST);
        }

        $validated = $validator->validated();

        $isUnique = ZoneMaster::validateUniqueZonCode(
            $validated['Zon_Code'],
            $validated['Org_Id'] ?? null
        );

        if (!$isUnique) {
            $orgText = $validated['Org_Id'] ? ' for the selected organization' : ' as a global zone';
            return response()->json([
                'success' => false,
                'message' => "Zone code '{$validated['Zon_Code']}' already exists{$orgText}"
            ], Response::HTTP_BAD_REQUEST);
        }

        $zone = ZoneMaster::create($validated);

        $zone->load('organisation');

        return response()->json([
            'success' => true,
            'message' => 'Zone created successfully',
            'data' => $zone
        ], Response::HTTP_CREATED);
    }

    public function show($id)
    {
        if (!is_numeric($id) || $id <= 0) {
            return response()->json([
                'success' => false,
                'message' => 'Invalid zone ID'
            ], Response::HTTP_BAD_REQUEST);
        }

        $zone = ZoneMaster::with('organisation')->find($id);

        if (!$zone) {
            return response()->json([
                'success' => false,
                'message' => 'Zone not found'
            ], Response::HTTP_NOT_FOUND);
        }

        $zone->full_zone = $zone->full_zone;
        $zone->organization_name = $zone->organization_name;
        $zone->is_global = $zone->isGlobal();

        return response()->json([
            'success' => true,
            'message' => 'Zone retrieved successfully',
            'data' => $zone
        ], Response::HTTP_OK);
    }


    public function update(Request $request, $id)
    {
        if (!is_numeric($id) || $id <= 0) {
            return response()->json([
                'success' => false,
                'message' => 'Invalid zone ID'
            ], Response::HTTP_BAD_REQUEST);
        }

        $zone = ZoneMaster::find($id);

        if (!$zone) {
            return response()->json([
                'success' => false,
                'message' => 'Zone not found'
            ], Response::HTTP_NOT_FOUND);
        }

        $validator = Validator::make($request->all(), [
            'Zon_Code' => 'sometimes|nullable|string|max:5',
            'Zon_Name' => 'sometimes|required|string|max:25',
            'Org_Id' => 'nullable|integer|exists:org_master,Org_Id'
        ], [
            'Zon_Code.max' => 'Zone code cannot exceed 5 characters',
            'Zon_Name.max' => 'Zone name cannot exceed 25 characters',
            'Org_Id.exists' => 'The selected organization does not exist'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation failed',
                'errors' => $validator->errors()
            ], Response::HTTP_BAD_REQUEST);
        }

        $validated = $validator->validated();

        if (isset($validated['Zon_Code'])) {
            $orgId = isset($validated['Org_Id']) ? $validated['Org_Id'] : $zone->Org_Id;

            $isUnique = ZoneMaster::validateUniqueZonCode(
                $validated['Zon_Code'],
                $orgId,
                $id
            );

            if (!$isUnique) {
                $orgText = $orgId ? ' for the selected organization' : ' as a global zone';
                return response()->json([
                    'success' => false,
                    'message' => "Zone code '{$validated['Zon_Code']}' already exists{$orgText}"
                ], Response::HTTP_BAD_REQUEST);
            }
        }

        $zone->update($validated);


        $zone->refresh();
        $zone->load('organisation');

        return response()->json([
            'success' => true,
            'message' => 'Zone updated successfully',
            'data' => $zone
        ], Response::HTTP_OK);
    }


    public function destroy($id)
    {
        if (!is_numeric($id) || $id <= 0) {
            return response()->json([
                'success' => false,
                'message' => 'Invalid zone ID'
            ], Response::HTTP_BAD_REQUEST);
        }

        $zone = ZoneMaster::find($id);

        if (!$zone) {
            return response()->json([
                'success' => false,
                'message' => 'Zone not found'
            ], Response::HTTP_NOT_FOUND);
        }

        if (!$zone->canBeDeleted()) {
            return response()->json([
                'success' => false,
                'message' => 'Cannot delete zone because it has associated records'
            ], Response::HTTP_CONFLICT);
        }

        $zone->delete();

        return response()->json([
            'success' => true,
            'message' => 'Zone deleted successfully'
        ], Response::HTTP_OK);
    }


    public function getByOrganization(Request $request, $orgId)
    {
        if ($orgId === 'null' || $orgId === '') {

            $query = ZoneMaster::withoutOrganization();
        } else {
            if (!is_numeric($orgId) || $orgId <= 0) {
                return response()->json([
                    'success' => false,
                    'message' => 'Invalid organization ID'
                ], Response::HTTP_BAD_REQUEST);
            }


            $organization = OrgMaster::find($orgId);
            if (!$organization) {
                return response()->json([
                    'success' => false,
                    'message' => 'Organization not found'
                ], Response::HTTP_NOT_FOUND);
            }

            $query = ZoneMaster::byOrganization($orgId);
        }


        $query->with('organisation');


        if ($request->has('search') && !empty($request->search)) {
            $query->search($request->search);
        }


        $sortField = $request->get('sort_by', 'Zon_Code');
        $sortDirection = $request->get('sort_dir', 'asc');
        $query->orderBy($sortField, $sortDirection);


        if ($request->has('paginate') && $request->paginate === 'false') {
            $zones = $query->get();
        } else {
            $perPage = $request->get('per_page', 15);
            $zones = $query->paginate($perPage);
        }


        $zonesCollection = $zones instanceof \Illuminate\Pagination\LengthAwarePaginator
            ? $zones->getCollection()
            : $zones;

        $zonesCollection->transform(function ($zone) {
            $zone->full_zone = $zone->full_zone;
            $zone->organization_name = $zone->organization_name;
            $zone->is_global = $zone->isGlobal();
            return $zone;
        });

        return response()->json([
            'success' => true,
            'message' => 'Zones retrieved successfully',
            'data' => $zones
        ], Response::HTTP_OK);
    }

    public function getGlobalZones(Request $request)
    {
        $query = ZoneMaster::withoutOrganization();


        if ($request->has('search') && !empty($request->search)) {
            $query->search($request->search);
        }


        $sortField = $request->get('sort_by', 'Zon_Code');
        $sortDirection = $request->get('sort_dir', 'asc');
        $query->orderBy($sortField, $sortDirection);


        $perPage = $request->get('per_page', 15);
        $zones = $query->paginate($perPage);


        $zones->getCollection()->transform(function ($zone) {
            $zone->full_zone = $zone->full_zone;
            $zone->organization_name = $zone->organization_name;
            $zone->is_global = true;
            return $zone;
        });

        return response()->json([
            'success' => true,
            'message' => 'Global zones retrieved successfully',
            'data' => $zones
        ], Response::HTTP_OK);
    }


    public function bulkStore(Request $request)
    {

        $validator = Validator::make($request->all(), [
            'zones' => 'required|array|min:1',
            'zones.*.Zon_Code' => 'required|string|max:5',
            'zones.*.Zon_Name' => 'required|string|max:25',
            'zones.*.Org_Id' => 'nullable|integer|exists:org_Master,Org_Id'
        ], [
            'zones.required' => 'Zones data is required',
            'zones.array' => 'Zones must be an array',
            'zones.min' => 'At least one zone is required',
            'zones.*.Zon_Code.required' => 'Zone code is required for all zones',
            'zones.*.Zon_Name.required' => 'Zone name is required for all zones',
            'zones.*.Org_Id.exists' => 'Organization does not exist'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation failed',
                'errors' => $validator->errors()
            ], Response::HTTP_BAD_REQUEST);
        }

        $zonesData = $request->zones;
        $createdZones = [];
        $errors = [];

        foreach ($zonesData as $index => $zoneData) {

            $isUnique = ZoneMaster::validateUniqueZonCode(
                $zoneData['Zon_Code'],
                $zoneData['Org_Id'] ?? null
            );

            if (!$isUnique) {
                $orgText = isset($zoneData['Org_Id']) ? ' for the selected organization' : ' as a global zone';
                $errors[] = "Row {$index}: Zone code '{$zoneData['Zon_Code']}' already exists{$orgText}";
                continue;
            }

            try {
                $zone = ZoneMaster::create($zoneData);
                $createdZones[] = $zone;
            } catch (\Exception $e) {
                $errors[] = "Row {$index}: " . $e->getMessage();
            }
        }

        if (!empty($errors)) {
            return response()->json([
                'success' => false,
                'message' => 'Some zones failed to create',
                'errors' => $errors,
                'created_count' => count($createdZones),
                'failed_count' => count($errors)
            ], Response::HTTP_BAD_REQUEST);
        }

        return response()->json([
            'success' => true,
            'message' => count($createdZones) . ' zone(s) created successfully',
            'data' => $createdZones
        ], Response::HTTP_CREATED);
    }
}
