<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Category;
use App\Models\City;
use App\Models\Country;
use App\Models\County;
use App\Models\District;
use App\Models\Province;
use App\Models\Village;
use App\Models\Zone;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

class ApiController extends Controller
{
    /**
     * Get all categories with hierarchy information
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function getCategories()
    {
        // Cache categories for better performance
        $categories = Cache::remember('admin_categories_hierarchical', 3600, function () {
            return Category::select('id', 'category_key', 'category_fa', 'category_en', 'parent_id', 'sort_order')
                ->orderBy('sort_order')
                ->orderBy('category_fa')
                ->get();
        });

        return response()->json($categories);
    }

    /**
     * Get provinces by country
     *
     * @param  int  $countryId
     * @return \Illuminate\Http\JsonResponse
     */
    public function getProvincesByCountry($countryId)
    {
        $provinces = Province::where('country_id', $countryId)
            ->where('is_active', 1)
            ->orderBy('name')
            ->get(['id', 'name']);

        return response()->json($provinces);
    }

    /**
     * Get counties by province
     *
     * @param  int  $provinceId
     * @return \Illuminate\Http\JsonResponse
     */
    public function getCountiesByProvince($provinceId)
    {
        $counties = County::where('province_id', $provinceId)
            ->where('is_active', 1)
            ->orderBy('name')
            ->get(['id', 'name']);

        return response()->json($counties);
    }

    /**
     * Get districts by county
     *
     * @param  int  $countyId
     * @return \Illuminate\Http\JsonResponse
     */
    public function getDistrictsByCounty($countyId)
    {
        $districts = District::where('county_id', $countyId)
            ->where('is_active', 1)
            ->orderBy('name')
            ->get(['id', 'name']);

        return response()->json($districts);
    }

    /**
     * Get cities by district
     *
     * @param  int  $districtId
     * @return \Illuminate\Http\JsonResponse
     */
    public function getCitiesByDistrict($districtId)
    {
        $cities = City::where('district_id', $districtId)
            ->where('is_active', 1)
            ->orderBy('name')
            ->get(['id', 'name']);

        return response()->json($cities);
    }

    /**
     * Get villages by district
     *
     * @param  int  $districtId
     * @return \Illuminate\Http\JsonResponse
     */
    public function getVillagesByDistrict($districtId)
    {
        $villages = Village::where('district_id', $districtId)
            ->where('is_active', 1)
            ->orderBy('name')
            ->get(['id', 'name']);

        return response()->json($villages);
    }

    /**
     * Get zones by city or village
     *
     * @param  string  $parentType  (city or village)
     * @param  int  $parentId
     * @return \Illuminate\Http\JsonResponse
     */
    public function getZonesByParent($parentType, $parentId)
    {
        if (! in_array($parentType, ['city', 'village'])) {
            return response()->json(['error' => 'Invalid parent type'], 400);
        }

        $zones = Zone::where($parentType.'_id', $parentId)
            ->whereNull('parent_zone_id') // Get only top-level zones
            ->where('is_active', 1)
            ->orderBy('name')
            ->get(['id', 'name']);

        return response()->json($zones);
    }

    /**
     * Get child zones by parent zone
     *
     * @param  int  $parentZoneId
     * @return \Illuminate\Http\JsonResponse
     */
    public function getChildZones($parentZoneId)
    {
        $zones = Zone::where('parent_zone_id', $parentZoneId)
            ->where('is_active', 1)
            ->orderBy('name')
            ->get(['id', 'name']);

        return response()->json($zones);
    }

    /**
     * Get boundary data for a specific region
     *
     * @param  string  $regionType  (country, province, county, district, city, village, zone)
     * @param  int  $regionId
     * @return \Illuminate\Http\JsonResponse
     */
    public function getBoundaryData($regionType, $regionId)
    {
        try {
            // Map the region type to the corresponding table and model
            $tableMapping = [
                'country' => ['table' => 'state1_countries', 'model' => Country::class],
                'province' => ['table' => 'state2_provinces', 'model' => Province::class],
                'county' => ['table' => 'state3_counties', 'model' => County::class],
                'district' => ['table' => 'state4_districts', 'model' => District::class],
                'city' => ['table' => 'state5_cities', 'model' => City::class],
                'village' => ['table' => 'state6_village', 'model' => Village::class],
                'zone' => ['table' => 'state7_zone', 'model' => Zone::class],
            ];

            // Check if the region type is valid
            if (! isset($tableMapping[$regionType])) {
                return response()->json(['error' => 'Invalid region type'], 400);
            }

            // Get the model class for the region type
            $modelClass = $tableMapping[$regionType]['model'];

            // Query the region data including boundaries
            $region = $modelClass::find($regionId);

            if (! $region) {
                return response()->json(['error' => 'Region not found'], 404);
            }

            // Check if the region has boundary data
            if (! $region->boundaries) {
                return response()->json(['error' => 'No boundary data available for this region'], 404);
            }

            // Convert the boundaries from database format to GeoJSON if needed
            $boundaryData = $region->boundaries;

            // In some cases, the boundary data might be stored as a custom MySQL geometry type
            // Convert it to GeoJSON for client-side rendering
            if (! is_array($boundaryData) && ! is_object($boundaryData)) {
                // If using MySQL's spatial data type, convert it to GeoJSON
                $boundaryQuery = DB::select("SELECT ST_AsGeoJSON(boundaries) as geojson_boundaries 
                                            FROM {$tableMapping[$regionType]['table']} 
                                            WHERE id = ?", [$regionId]);

                if (! empty($boundaryQuery) && isset($boundaryQuery[0]->geojson_boundaries)) {
                    $boundaryData = json_decode($boundaryQuery[0]->geojson_boundaries);
                }
            }

            // Return the region data with boundaries
            return response()->json([
                'id' => $region->id,
                'name' => $region->name,
                'boundaries' => $boundaryData,
            ]);

        } catch (\Exception $e) {
            return response()->json(['error' => 'Failed to fetch boundary data: '.$e->getMessage()], 500);
        }
    }
}
