<?php

namespace App\Services;

use App\Models\Grievance;
use App\Repositories\GrievanceRepository;
use App\ResponseHandler\Response;
use Illuminate\Http\Response as LaravelResponse;
use Illuminate\Support\Facades\Validator;

class GrievanceService
{
    protected $grievanceRepository;
    protected $response;

    public function __construct(GrievanceRepository $grievanceRepository, Response $response)
    {
        $this->grievanceRepository = $grievanceRepository;
        $this->response = $response;
    }

    /**
     * Create a new grievance
     */
    public function createGrievance(array $data)
    {
        // Validate input
        $validator = $this->validateGrievance($data);
        if ($validator->fails()) {
            return $this->response->respondWithValidationError($validator->errors());
        }

        // Set reported_at to current timestamp if not provided
        if (!isset($data['reported_at'])) {
            $data['reported_at'] = now();
        }

        // Set default status if not provided
        if (!isset($data['status'])) {
            $data['status'] = Grievance::STATUS_OPEN;
        }

        $grievance = $this->grievanceRepository->create($data);

        return $this->response->respondWithData(
            'Grievance created successfully',
            $grievance,
            new LaravelResponse
        );
    }

    /**
     * Update an existing grievance
     */
    public function updateGrievance($id, array $data)
    {
        // Validate input
        $validator = $this->validateGrievance($data, true);
        if ($validator->fails()) {
            return $this->response->respondWithValidationError($validator->errors());
        }

        // If status is being changed to CLOSED, set closed_at
        if (isset($data['status']) && $data['status'] === Grievance::STATUS_CLOSED && !isset($data['closed_at'])) {
            $data['closed_at'] = now();
        }

        $grievance = $this->grievanceRepository->update($id, $data);

        if (!$grievance) {
            return $this->response->respondWithError('Grievance not found', 404);
        }

        return $this->response->respondWithData(
            'Grievance updated successfully',
            $grievance,
            new LaravelResponse
        );
    }

    /**
     * Get grievance by ID
     */
    public function getGrievanceById($id)
    {
        $grievance = $this->grievanceRepository->getById($id);

        if (!$grievance) {
            return $this->response->respondWithError('Grievance not found', 404);
        }

        return $this->response->respondWithData(
            'Grievance retrieved successfully',
            $grievance,
            new LaravelResponse
        );
    }

    /**
     * Get all grievances by status
     */
    public function getAllByStatus($status, $perPage = 20)
    {
        // Validate status
        if (!in_array($status, Grievance::getStatuses())) {
            return $this->response->respondWithError('Invalid status value', 400);
        }

        $query = Grievance::where('status', $status)
                          ->with(['voter', 'rationCard'])
                          ->orderBy('target_resolve_by', 'asc')
                          ->orderBy('reported_at', 'desc');

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

        return $this->response->respondWithData(
            'Grievances retrieved successfully',
            [
                'grievances' => $grievances->items(),
                'status' => $status,
                'pagination' => [
                    'total' => $grievances->total(),
                    'per_page' => $grievances->perPage(),
                    'current_page' => $grievances->currentPage(),
                    'last_page' => $grievances->lastPage(),
                    'from' => $grievances->firstItem(),
                    'to' => $grievances->lastItem(),
                ],
            ],
            new LaravelResponse
        );
    }

    /**
     * Get all grievances
     */
    public function getAllGrievances($status = null, $perPage = 20)
    {
        if ($status && !in_array($status, Grievance::getStatuses())) {
            return $this->response->respondWithError('Invalid status value', 400);
        }

        $query = Grievance::with(['voter', 'rationCard'])
                          ->orderBy('reported_at', 'desc');

        if ($status) {
            $query->where('status', $status);
        }

        $grievances = $query->paginate($perPage);
        $counts = $this->grievanceRepository->getCountsByStatus();

        return $this->response->respondWithData(
            'Grievances retrieved successfully',
            [
                'grievances' => $grievances->items(),
                'status_counts' => $counts,
                'pagination' => [
                    'total' => $grievances->total(),
                    'per_page' => $grievances->perPage(),
                    'current_page' => $grievances->currentPage(),
                    'last_page' => $grievances->lastPage(),
                    'from' => $grievances->firstItem(),
                    'to' => $grievances->lastItem(),
                ],
            ],
            new LaravelResponse
        );
    }

    /**
     * Get grievances by voter ID
     */
    public function getByVoterId($voterId, $perPage = 20)
    {
        $query = Grievance::where('voter_id', $voterId)
                          ->with(['voter', 'rationCard'])
                          ->orderBy('reported_at', 'desc');

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

        return $this->response->respondWithData(
            'Grievances retrieved successfully',
            [
                'grievances' => $grievances->items(),
                'voter_id' => $voterId,
                'pagination' => [
                    'total' => $grievances->total(),
                    'per_page' => $grievances->perPage(),
                    'current_page' => $grievances->currentPage(),
                    'last_page' => $grievances->lastPage(),
                    'from' => $grievances->firstItem(),
                    'to' => $grievances->lastItem(),
                ],
            ],
            new LaravelResponse
        );
    }

    /**
     * Get grievances by ration card number
     */
    public function getByRationCardNumber($rationCardNumber, $perPage = 20)
    {
        $query = Grievance::where('ration_card_number', $rationCardNumber)
                          ->with(['voter', 'rationCard'])
                          ->orderBy('reported_at', 'desc');

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

        return $this->response->respondWithData(
            'Grievances retrieved successfully',
            [
                'grievances' => $grievances->items(),
                'ration_card_number' => $rationCardNumber,
                'pagination' => [
                    'total' => $grievances->total(),
                    'per_page' => $grievances->perPage(),
                    'current_page' => $grievances->currentPage(),
                    'last_page' => $grievances->lastPage(),
                    'from' => $grievances->firstItem(),
                    'to' => $grievances->lastItem(),
                ],
            ],
            new LaravelResponse
        );
    }

    /**
     * Delete a grievance
     */
    public function deleteGrievance($id)
    {
        $result = $this->grievanceRepository->delete($id);

        if (!$result) {
            return $this->response->respondWithError('Grievance not found', 404);
        }

        return $this->response->respondWithData(
            'Grievance deleted successfully',
            null,
            new LaravelResponse
        );
    }

    /**
     * Get paginated grievances with optional ration card search
     */
    public function getPaginatedGrievances($rationCardNumber = null, $perPage = 15, $status = null)
    {
        // Validate status if provided
        if ($status && !in_array($status, Grievance::getStatuses())) {
            return $this->response->respondWithError('Invalid status value', 400);
        }

        // Validate pagination parameters
        $perPage = max(1, min($perPage, 100)); // Limit between 1 and 100

        try {
            $grievances = $this->grievanceRepository->getPaginatedGrievances($rationCardNumber, $perPage, $status);
            // Get filtered counts based on ration card number instead of overall counts
            $counts = $this->grievanceRepository->getFilteredCountsByStatus($rationCardNumber);

            $responseData = [
                'grievances' => $grievances->items(),
                'pagination' => [
                    'current_page' => $grievances->currentPage(),
                    'last_page' => $grievances->lastPage(),
                    'per_page' => $grievances->perPage(),
                    'total' => $grievances->total(),
                    'from' => $grievances->firstItem(),
                    'to' => $grievances->lastItem(),
                    'has_more_pages' => $grievances->hasMorePages(),
                    'prev_page_url' => $grievances->previousPageUrl(),
                    'next_page_url' => $grievances->nextPageUrl(),
                ],
                'search_criteria' => [
                    'ration_card_number' => $rationCardNumber,
                    'status' => $status,
                ],
                'status_counts' => $counts,
            ];

            $message = $rationCardNumber 
                ? "Grievances for ration card '{$rationCardNumber}' retrieved successfully" 
                : 'All grievances retrieved successfully';

            return $this->response->respondWithData(
                $message,
                $responseData,
                new LaravelResponse
            );

        } catch (\Exception $e) {
            return $this->response->respondWithError(
                'Failed to retrieve grievances: ' . $e->getMessage(), 
                500
            );
        }
    }

    /**
     * Get all grievances paginated
     */
    public function getAllGrievancesPaginated($status = null, $perPage = 15)
    {
        // Validate status if provided
        if ($status && !in_array($status, Grievance::getStatuses())) {
            return $this->response->respondWithError('Invalid status value', 400);
        }

        // Validate pagination parameters
        $perPage = max(1, min($perPage, 100)); // Limit between 1 and 100

        try {
            $grievances = $this->grievanceRepository->getAllPaginated($status, $perPage);
            $counts = $this->grievanceRepository->getCountsByStatus();

            $responseData = [
                'grievances' => $grievances->items(),
                'pagination' => [
                    'current_page' => $grievances->currentPage(),
                    'last_page' => $grievances->lastPage(),
                    'per_page' => $grievances->perPage(),
                    'total' => $grievances->total(),
                    'from' => $grievances->firstItem(),
                    'to' => $grievances->lastItem(),
                    'has_more_pages' => $grievances->hasMorePages(),
                    'prev_page_url' => $grievances->previousPageUrl(),
                    'next_page_url' => $grievances->nextPageUrl(),
                ],
                'filter' => [
                    'status' => $status,
                ],
                'status_counts' => $counts,
            ];

            return $this->response->respondWithData(
                'Grievances retrieved successfully',
                $responseData,
                new LaravelResponse
            );

        } catch (\Exception $e) {
            return $this->response->respondWithError(
                'Failed to retrieve grievances: ' . $e->getMessage(), 
                500
            );
        }
    }

    /**
     * Validate grievance data
     */
    private function validateGrievance(array $data, $isUpdate = false)
    {
        $rules = [
            'voter_id' => 'nullable|string|max:255',
            'ration_card_number' => 'nullable|string|max:255',
            'title' => ($isUpdate ? 'sometimes|' : '') . 'required|string|max:160',
            'description' => 'nullable|string',
            'status' => 'nullable|in:' . implode(',', Grievance::getStatuses()),
            'meeting_date' => 'nullable|date',
            'reported_at' => 'nullable|date',
            'target_resolve_by' => 'nullable|date',
            'closed_at' => 'nullable|date',
        ];

        // Custom validation: At least one of voter_id or ration_card_number should be present (optional based on requirements)
        // Commenting this out as per requirement: "in some time, both voter_id and ration_card_number both may be null"
        // $rules['voter_id'] = 'required_without:ration_card_number|nullable|string|max:255';
        // $rules['ration_card_number'] = 'required_without:voter_id|nullable|string|max:255';

        return Validator::make($data, $rules);
    }
}
