<?php

namespace PloverCRM\Core\Api\V1;

use PloverCRM\Common\Permissions;
use PloverCRM\Core\Api\AbstractEndpoint;
use PloverCRM\Core\Services\SystemFieldProvisioner;
use PloverCRM\Core\Services\SystemFieldRegistry;
use WP_REST_Request;

/**
 * Stages Endpoint
 * 
 * GET /wp-json/plover-crm/v1/stages - Get all stages with usage counts
 * PUT /wp-json/plover-crm/v1/stages - Update stages (with cascade rename and deletion protection)
 */
class StagesEndpoint extends AbstractEndpoint
{
    const STAGE_FIELD_SLUG = SystemFieldRegistry::FIELD_STAGE;

    public function getRoute(): string
    {
        return '/stages';
    }

    public function getMethod()
    {
        return ['GET', 'PUT'];
    }

    public function handle(WP_REST_Request $request)
    {
        $crm = $this->container->get('crm');

        if (!$crm || !$crm->isAvailable()) {
            return $this->error('CRM not available', 503);
        }

        if ($request->get_method() === 'GET') {
            if (!Permissions::canAccessSetting('stages', 'view')) {
                return $this->error(
                    'You do not have permission to view stages.',
                    403,
                    'stages_read_permission_denied'
                );
            }

            return $this->getStages($crm);
        }

        if (!Permissions::canAccessSetting('stages', 'manage')) {
            return $this->error(
                'You do not have permission to manage stages.',
                403,
                'stages_manage_permission_denied'
            );
        }

        return $this->updateStages($request, $crm);
    }

    /**
     * Get all stages with colors and usage counts
     */
    private function getStages($crm)
    {
        $stages = $this->getCurrentStages($crm);
        $colors = get_option('plover_crm_stage_colors', []);

        $result = [];
        foreach ($stages as $index => $stage) {
            $result[] = [
                'name' => $stage,
                'color' => $colors[$stage] ?? '#666666',
                'contacts_count' => $this->getStageUsageCount($crm, $stages, $stage, $index),
            ];
        }

        return $this->success([
            'stages' => $result
        ]);
    }

    /**
     * Update stages with cascade rename and deletion protection
     */
    private function updateStages(WP_REST_Request $request, $crm)
    {
        $data = $request->get_json_params();

        if (!isset($data['stages']) || !is_array($data['stages'])) {
            return $this->error('Invalid stages data', 400);
        }

        // Get current stages for comparison
        $currentStages = $this->getCurrentStages($crm);

        // Parse new stages - support both formats:
        // 1. Simple: [{ name: "New", color: "#fff" }]
        // 2. With old_name for rename: [{ name: "Fresh Lead", old_name: "New", color: "#fff" }]
        $newStages = [];
        $newColors = [];
        $renames = []; // old_name => new_name

        foreach ($data['stages'] as $stage) {
            if (!isset($stage['name']) || empty(trim($stage['name']))) {
                continue;
            }

            $name = trim($stage['name']);
            $newStages[] = $name;
            $newColors[$name] = $stage['color'] ?? '#666666';

            // Check if this is a rename operation
            if (isset($stage['old_name']) && !empty(trim($stage['old_name']))) {
                $oldName = trim($stage['old_name']);
                if ($oldName !== $name && in_array($oldName, $currentStages)) {
                    $renames[$oldName] = $name;
                }
            }
        }

        if (empty($newStages)) {
            return $this->error('At least one stage is required', 400);
        }

        // Detect deleted stages (stages in current but not in new, and not renamed)
        $renamedOldNames = array_keys($renames);
        $deletedStages = [];

        foreach ($currentStages as $currentStage) {
            // Stage is deleted if:
            // 1. Not in new stages list
            // 2. Not being renamed to something else
            if (!in_array($currentStage, $newStages) && !in_array($currentStage, $renamedOldNames)) {
                $deletedStages[] = $currentStage;
            }
        }

        // Check if any deleted stage is in use
        $stagesInUse = [];
        foreach ($deletedStages as $deletedStage) {
            $deletedStageIndex = array_search($deletedStage, $currentStages, true);
            if ($deletedStageIndex === false) {
                continue;
            }

            $count = $this->getStageUsageCount($crm, $currentStages, $deletedStage, (int) $deletedStageIndex);
            if ($count > 0) {
                $stagesInUse[] = [
                    'name' => $deletedStage,
                    'contacts_count' => $count
                ];
            }
        }

        if (!empty($stagesInUse)) {
            return $this->error(
                'Cannot delete stages that are assigned to contacts. Please reassign contacts first.',
                400,
                [
                    'code' => 'stages_in_use',
                    'stages_in_use' => $stagesInUse
                ]
            );
        }

        // Perform cascade updates for renamed stages
        $updatedContacts = 0;
        foreach ($renames as $oldName => $newName) {
            $count = $crm->updateCustomFieldValue(self::STAGE_FIELD_SLUG, $oldName, $newName);
            $updatedContacts += $count;
        }

        // Update colors option
        update_option('plover_crm_stage_colors', $newColors);

        // Update the canonical system-managed stage field definition
        $provisioner = new SystemFieldProvisioner($this->container);
        $provisioner->syncStageField($newStages);

        // Build response with updated counts
        $result = [];
        foreach ($newStages as $index => $stage) {
            $result[] = [
                'name' => $stage,
                'color' => $newColors[$stage],
                'contacts_count' => $this->getStageUsageCount($crm, $newStages, $stage, $index),
            ];
        }

        $response = [
            'stages' => $result,
            'message' => 'Stages updated successfully'
        ];

        // Include rename info if any renames occurred
        if (!empty($renames)) {
            $response['renames'] = $renames;
            $response['contacts_updated'] = $updatedContacts;
        }

        return $this->success($response);
    }

    /**
     * Get current stages from CRM
     */
    private function getCurrentStages($crm): array
    {
        $existingFields = $crm->getAllCustomFields();

        foreach ($existingFields as $field) {
            if ($field['slug'] === self::STAGE_FIELD_SLUG && isset($field['options'])) {
                return $field['options'];
            }
        }

        return [];
    }

    private function getStageUsageCount($crm, array $stages, string $stage, int $index): int
    {
        $count = (int) $crm->countContactsWithCustomFieldValue(self::STAGE_FIELD_SLUG, $stage);

        if ($index === 0 && !empty($stages) && $stages[0] === $stage) {
            $count += (int) $crm->countContactsWithoutCustomField(self::STAGE_FIELD_SLUG);
        }

        return $count;
    }
}
