<?php

namespace EasyLinkAutomations\HTTP\Controllers;

if (!defined('ABSPATH')) {
    exit;
}

use EasyLinkAutomations\Config;
use EasyLinkAutomations\Data\ProCatalog;
use EasyLinkAutomations\HTTP\Request\Request;
use EasyLinkAutomations\HTTP\Response;
use EasyLinkAutomations\Models\Automation;
use EasyLinkAutomations\Models\AutomationAction;

/**
 * Handles CRUD operations for automation workflows.
 */
final class AutomationController
{
    public function index(Request $request): Response
    {
        $page    = (int) ($request->get('page') ?? 1);
        $perPage = (int) ($request->get('per_page') ?? 20);
        $status  = $request->get('status');

        $result = Automation::paginate($page, $perPage, $status);

        $isProActive = Config::isProActivated();
        $proSlugs    = $isProActive ? [] : self::getProSlugs();

        // Load actions for each automation and decode JSON fields
        foreach ($result['items'] as &$automation) {
            $automation['trigger_data'] = json_decode($automation['trigger_data'] ?? '{}', true) ?? [];
            $actions = AutomationAction::findByAutomation((int) $automation['id']);
            foreach ($actions as &$action) {
                $action['config'] = json_decode($action['config'] ?? '{}', true) ?? [];
            }
            $automation['actions'] = $actions;

            // Flag automations that use pro components when license is inactive
            $automation['requires_pro_license'] = false;
            if (!$isProActive) {
                $automation['requires_pro_license'] = self::automationUsesProSlugs($automation, $proSlugs);
            }
        }

        return Response::success([
            'automations' => $result['items'],
            'total'       => $result['total'],
            'page'        => $page,
            'per_page'    => $perPage,
        ]);
    }

    public function show(Request $request): Response
    {
        $automationId = (int) ($request->get('id') ?? 0);

        if (!$automationId) {
            return Response::error(__('Automation ID is required', 'easylink-automations'))->httpStatus(400);
        }

        $automation = Automation::find($automationId);

        if (!$automation) {
            return Response::error(__('Automation not found', 'easylink-automations'))->httpStatus(404);
        }

        // Load actions
        $automation['actions'] = AutomationAction::findByAutomation($automationId);

        // Parse JSON fields
        $automation['trigger_data'] = json_decode($automation['trigger_data'] ?? '{}', true);
        $automation['config']       = json_decode($automation['config'] ?? '{}', true);

        foreach ($automation['actions'] as &$action) {
            $action['config'] = json_decode($action['config'] ?? '{}', true);
        }

        return Response::success(['automation' => $automation]);
    }

    public function store(Request $request): Response
    {
        $title         = sanitize_text_field($request->get('title') ?? '');
        $triggerSlug   = sanitize_text_field($request->get('trigger_slug') ?? '');
        $triggerConfig = $request->get('trigger_config') ?? [];
        $actions       = $request->get('actions') ?? [];
        $status        = sanitize_text_field($request->get('status') ?? 'draft');

        // Decode JSON strings if they were sent as strings (from FormData)
        if (is_string($triggerConfig)) {
            $triggerConfig = json_decode($triggerConfig, true) ?? [];
        }
        if (is_string($actions)) {
            $actions = json_decode($actions, true) ?? [];
        }

        // Validate required fields
        if (empty($title)) {
            return Response::error(__('Title is required', 'easylink-automations'))->httpStatus(400);
        }

        if (empty($triggerSlug)) {
            return Response::error(__('Trigger is required', 'easylink-automations'))->httpStatus(400);
        }

        if (empty($actions) || !is_array($actions)) {
            return Response::error(__('At least one action is required', 'easylink-automations'))->httpStatus(400);
        }

        // Create the automation
        $automationId = Automation::create([
            'title'        => $title,
            'status'       => $status,
            'trigger_type' => $triggerSlug,
            'trigger_data' => wp_json_encode($triggerConfig),
            'created_by'   => get_current_user_id(),
        ]);

        if (!$automationId) {
            return Response::error(__('Failed to create automation', 'easylink-automations'))->httpStatus(500);
        }

        // Create actions
        foreach ($actions as $order => $actionData) {
            $actionSlug   = sanitize_text_field($actionData['action_slug'] ?? '');
            $actionConfig = $actionData['config'] ?? [];

            // Decode config if it was sent as a JSON string (e.g. from list page toggle)
            if (is_string($actionConfig)) {
                $actionConfig = json_decode($actionConfig, true) ?? [];
            }

            if (empty($actionSlug)) {
                continue;
            }

            AutomationAction::create([
                'automation_id' => $automationId,
                'action_slug'   => $actionSlug,
                'config'        => wp_json_encode($actionConfig),
                'action_order'  => $order,
            ]);
        }

        return Response::success([
            'message'       => __('Automation created successfully', 'easylink-automations'),
            'automation_id' => $automationId,
        ]);
    }

    public function update(Request $request): Response
    {
        $automationId  = (int) ($request->get('id') ?? 0);
        $title         = sanitize_text_field($request->get('title') ?? '');
        $triggerSlug   = sanitize_text_field($request->get('trigger_slug') ?? '');
        $triggerConfig = $request->get('trigger_config') ?? [];
        $actions       = $request->get('actions') ?? [];
        $status        = sanitize_text_field($request->get('status') ?? 'draft');

        // Decode JSON strings if they were sent as strings (from FormData)
        if (is_string($triggerConfig)) {
            $triggerConfig = json_decode($triggerConfig, true) ?? [];
        }
        if (is_string($actions)) {
            $actions = json_decode($actions, true) ?? [];
        }

        if (!$automationId) {
            return Response::error(__('Automation ID is required', 'easylink-automations'))->httpStatus(400);
        }

        $automation = Automation::find($automationId);
        if (!$automation) {
            return Response::error(__('Automation not found', 'easylink-automations'))->httpStatus(404);
        }

        // Update automation
        $updated = Automation::update($automationId, [
            'title'        => $title,
            'status'       => $status,
            'trigger_type' => $triggerSlug,
            'trigger_data' => wp_json_encode($triggerConfig),
        ]);

        if (!$updated) {
            return Response::error(__('Failed to update automation', 'easylink-automations'))->httpStatus(500);
        }

        // Delete existing actions and recreate
        AutomationAction::deleteByAutomation($automationId);

        foreach ($actions as $order => $actionData) {
            $actionSlug   = sanitize_text_field($actionData['action_slug'] ?? '');
            $actionConfig = $actionData['config'] ?? [];

            // Decode config if it was sent as a JSON string (e.g. from list page toggle)
            if (is_string($actionConfig)) {
                $actionConfig = json_decode($actionConfig, true) ?? [];
            }

            if (empty($actionSlug)) {
                continue;
            }

            AutomationAction::create([
                'automation_id' => $automationId,
                'action_slug'   => $actionSlug,
                'config'        => wp_json_encode($actionConfig),
                'action_order'  => $order,
            ]);
        }

        return Response::success([
            'message'       => __('Automation updated successfully', 'easylink-automations'),
            'automation_id' => $automationId,
        ]);
    }

    public function toggleStatus(Request $request): Response
    {
        $automationId = (int) ($request->get('id') ?? 0);

        if (!$automationId) {
            return Response::error(__('Automation ID is required', 'easylink-automations'))->httpStatus(400);
        }

        $automation = Automation::find($automationId);
        if (!$automation) {
            return Response::error(__('Automation not found', 'easylink-automations'))->httpStatus(404);
        }

        $newStatus = $automation['status'] === 'active' ? 'paused' : 'active';

        $updated = Automation::update($automationId, [
            'status' => $newStatus,
        ]);

        if (!$updated) {
            return Response::error(__('Failed to update automation status', 'easylink-automations'))->httpStatus(500);
        }

        return Response::success([
            'message' => $newStatus === 'active'
                ? __('Automation activated', 'easylink-automations')
                : __('Automation paused', 'easylink-automations'),
            'status'  => $newStatus,
        ]);
    }

    public function duplicate(Request $request): Response
    {
        $automationId = (int) ($request->get('id') ?? 0);

        if (!$automationId) {
            return Response::error(__('Automation ID is required', 'easylink-automations'))->httpStatus(400);
        }

        $automation = Automation::find($automationId);
        if (!$automation) {
            return Response::error(__('Automation not found', 'easylink-automations'))->httpStatus(404);
        }

        // Create duplicated automation
        $newId = Automation::create([
            'title'        => $automation['title'] . ' (Copy)',
            'status'       => 'draft',
            'trigger_type' => $automation['trigger_type'],
            'trigger_data' => $automation['trigger_data'],
            'created_by'   => get_current_user_id(),
        ]);

        if (!$newId) {
            return Response::error(__('Failed to duplicate automation', 'easylink-automations'))->httpStatus(500);
        }

        // Duplicate actions
        $actions = AutomationAction::findByAutomation($automationId);
        foreach ($actions as $action) {
            AutomationAction::create([
                'automation_id' => $newId,
                'action_slug'   => $action['action_slug'],
                'config'        => $action['config'],
                'action_order'  => $action['action_order'],
            ]);
        }

        return Response::success([
            'message'       => __('Automation duplicated successfully', 'easylink-automations'),
            'automation_id' => $newId,
        ]);
    }

    public function destroy(Request $request): Response
    {
        $automationId = (int) ($request->get('id') ?? 0);

        if (!$automationId) {
            return Response::error(__('Automation ID is required', 'easylink-automations'))->httpStatus(400);
        }

        $automation = Automation::find($automationId);
        if (!$automation) {
            return Response::error(__('Automation not found', 'easylink-automations'))->httpStatus(404);
        }

        // Delete automation (actions will be cascade deleted by FK)
        $deleted = Automation::delete($automationId);

        if (!$deleted) {
            return Response::error(__('Failed to delete automation', 'easylink-automations'))->httpStatus(500);
        }

        return Response::success([
            'message' => __('Automation deleted successfully', 'easylink-automations'),
        ]);
    }

    /**
     * Collect all pro trigger and action slugs from the catalog.
     *
     * @return array{triggers: array<string, true>, actions: array<string, true>}
     */
    private static function getProSlugs(): array
    {
        $triggerSlugs = [];
        foreach (ProCatalog::triggers() as $trigger) {
            $triggerSlugs[$trigger['slug']] = true;
        }

        $actionSlugs = [];
        foreach (ProCatalog::actions() as $action) {
            $actionSlugs[$action['slug']] = true;
        }

        return ['triggers' => $triggerSlugs, 'actions' => $actionSlugs];
    }

    /**
     * Check if an automation uses any pro trigger or action.
     */
    private static function automationUsesProSlugs(array $automation, array $proSlugs): bool
    {
        $triggerSlug = $automation['trigger_type'] ?? '';
        if (isset($proSlugs['triggers'][$triggerSlug])) {
            return true;
        }

        foreach ($automation['actions'] ?? [] as $action) {
            $actionSlug = $action['action_slug'] ?? '';
            if (isset($proSlugs['actions'][$actionSlug])) {
                return true;
            }
        }

        return false;
    }
}
