<?php

/**
 * Dashboard Controller V1
 *
 * @package Licenzo\Http\Controller\Api\V1
 */

namespace Licenzo\Http\Controller\Api\V1;

use Licenzo\Framework\Http\Request;
use Licenzo\Model\Subscription;
use Licenzo\Model\SubscriptionTransaction;

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Subscription API controller for managing subscriptions
 */
class SubscriptionController
{

    /**
     * List customers with pagination and filtering
     */
    public function index(Request $request)
    {
        $search = $request->getSafe('search', 'sanitize_text_field');
        $status = $request->getSafe('status', 'sanitize_text_field');
        global $wpdb;
        $escapedSearch = $search ? $wpdb->esc_like($search) : '';
        $subscriptions = Subscription::with(['subscriptionProducts', 'customer'])
            ->when($escapedSearch, fn($query) => $query->whereHas(
                'customer',
                fn($q) => $q->where('first_name', 'like', "%{$escapedSearch}%")
                    ->orWhere('last_name', 'like', "%{$escapedSearch}%")
            ))
            ->when($status, fn($query) => $query->where('status', $status))
            ->orderBy('created_at', 'desc')
            ->paginate();

        return [
            'success' => true,
            'subscriptions' => $subscriptions
        ];
    }

    /**
     * Get a single subscription by ID
     */
    public function show($id)
    {
        $subscription = Subscription::with(['subscriptionProducts', 'customer', 'licenses', 'transactions'])->find($id);
        if (!$subscription) {
            return [
                'success' => false,
                'message' => __('Subscription not found', 'licenzo'),
            ];
        }

        if ($subscription->customer) {
            $subscription->customer->lifetime_value = $subscription->customer->lifetime_value;
        }

        return [
            'success'      => true,
            'subscription' => $subscription,
        ];
    }

    /**
     * Store a new subscription with products, transaction, and event
     */
    public function store(Request $request)
    {
        $data = $request->getSafe([
            'customer_id'       => 'absint',
            'subscription_name' => 'sanitize_text_field',
            'provider'          => 'sanitize_text_field',
            'provider_id'       => 'sanitize_text_field',
            'billing_cycle'  => 'sanitize_text_field',
            'recurring_amount'  => 'floatval',
            'billing_total_cycles'        => 'absint',
            'trial_days'        => 'absint',
            'status'            => 'sanitize_text_field',
            'next_billing_date' => 'sanitize_text_field',
            'amount'            => 'floatval',
            'generator'         => 'sanitize_text_field',
            'generated_license_key' => 'sanitize_text_field',
        ]);
        $data['products'] = array_map(function ($product) {
            return [
                'product_id'   => isset($product['product_id']) ? absint($product['product_id']) : 0,
                'variation_id' => isset($product['variation_id']) ? absint($product['variation_id']) : 0,
                'quantity'     => isset($product['quantity']) ? absint($product['quantity']) : 1,
            ];
        }, $request->get('products', []));

        // name validation
        if (empty($data['subscription_name'])) {
            return [
                'success' => false,
                'message'   => __('Subscription name is required', 'licenzo'),
            ];
        }
        // unique name validation
        if (Subscription::where('subscription_name', $data['subscription_name'])->exists()) {
            return [
                'success' => false,
                'message'   => __('Subscription name must be unique', 'licenzo'),
            ];
        }

        // Create subscription
        $subscriptionResult = \Licenzo\Services\SubscriptionService::create([
            'customer_id'       => $data['customer_id'],
            'subscription_name' => $data['subscription_name'],
            'provider'          => $data['provider'] ?? null,
            'provider_id'       => $data['provider_id'] ?? null,
            'currency'          => $data['currency'] ?? (function_exists('get_woocommerce_currency') ? get_woocommerce_currency() : 'USD'),
            'billing_cycle'  => $data['billing_cycle'],
            'recurring_amount'  => $data['recurring_amount'],
            'billing_total_cycles'        => $data['billing_total_cycles'],
            'trial_days'        => $data['trial_days'],
            'status'            => $data['status'],
            'next_billing_date' => $data['next_billing_date'],
            'amount'            => $data['amount'],
            'products'          => $data['products'],
            'generator'         => $data['generator'],
            'generated_license_key' => $data['generated_license_key'],
        ]);


        if (!$subscriptionResult['success']) {
            return [
                'success' => false,
                'message'   => $subscriptionResult['message'] ?? __('Failed to create subscription', 'licenzo'),
            ];
        }
        $subscriptionId = $subscriptionResult['subscription_id'];
        // Add initial transaction
        $transactionResult = \Licenzo\Services\SubscriptionService::addTransaction($subscriptionId, [
            'amount'           => $data['amount'],
            'status'           => SubscriptionTransaction::STATUS_SUCCESS,
            'transaction_date' => gmdate('Y-m-d H:i:s'),
        ]);
        if (!$transactionResult['success']) {
            return [
                'success' => false,
                'message'   => $transactionResult['message'] ?? __('Failed to add transaction', 'licenzo'),
            ];
        }
        return [
            'success'         => true,
            'subscription_id' => $subscriptionId,
        ];
    }

    public function update($id, Request $request)
    {
        $data = $request->getSafe([
            'customer_id'       => 'absint',
            'subscription_name' => 'sanitize_text_field',
            'provider'          => 'sanitize_text_field',
            'provider_id'       => 'sanitize_text_field',
            'billing_cycle'  => 'sanitize_text_field',
            'recurring_amount'  => 'floatval',
            'billing_total_cycles'        => 'absint',
            'trial_days'        => 'absint',
            'status'            => 'sanitize_text_field',
            'next_billing_date' => 'sanitize_text_field',
            'amount'            => 'floatval',
            'generator'         => 'sanitize_text_field',
            'generated_license_key' => 'sanitize_text_field',
        ]);
        $data['products'] = array_map(function ($product) {
            return [
                'product_id'   => isset($product['product_id']) ? absint($product['product_id']) : 0,
                'variation_id' => isset($product['variation_id']) ? absint($product['variation_id']) : 0,
                'quantity'     => isset($product['quantity']) ? absint($product['quantity']) : 1,
            ];
        }, $request->get('products', []));

        // name validation
        if (empty($data['subscription_name'])) {
            return [
                'success' => false,
                'message'   => __('Subscription name is required', 'licenzo'),
            ];
        }
        // unique name validation
        if (Subscription::where('subscription_name', $data['subscription_name'])->where('id', '!=', $id)->exists()) {
            return [
                'success' => false,
                'message'   => __('Subscription name must be unique', 'licenzo'),
            ];
        }


        // Update subscription
        $subscriptionResult = \Licenzo\Services\SubscriptionService::update($id, $data);

        return [
            'success'      => true,
            'subscription' => $subscriptionResult,
        ];
    }

    public function pause($id)
    {
        $result = \Licenzo\Services\SubscriptionService::pause((int) $id);

        if (isset($result['success']) && $result['success'] === false) {
            return $result;
        }

        return [
            'success'      => true,
            'subscription' => $result,
        ];
    }

    public function resume($id)
    {
        $result = \Licenzo\Services\SubscriptionService::resume((int) $id);

        if (isset($result['success']) && $result['success'] === false) {
            return $result;
        }

        return [
            'success'      => true,
            'subscription' => $result,
        ];
    }

    public function cancel($id, Request $request)
    {
        $reason = $request->getSafe('reason', 'sanitize_textarea_field');
        $result = \Licenzo\Services\SubscriptionService::cancel((int) $id, $reason ?: null);

        if (isset($result['success']) && $result['success'] === false) {
            return $result;
        }

        return [
            'success'      => true,
            'subscription' => $result,
        ];
    }

    public function addTransaction($id, Request $request)
    {
        try {
            $data = $request->getSafe([
                'transaction_type' => 'sanitize_text_field',
                'amount'           => 'floatval',
                'status'           => 'sanitize_text_field',
                'transaction_date' => 'sanitize_text_field',
                'notes'            => 'sanitize_textarea_field',
            ]);

            $result = \Licenzo\Services\SubscriptionService::addTransaction((int) $id, $data);

            if (!$result['success']) {
                return [
                    'success' => false,
                    'message' => $result['message'] ?? __('Failed to add transaction', 'licenzo'),
                ];
            }

            $transaction = SubscriptionTransaction::find($result['transaction_id']);

            return [
                'success'     => true,
                'transaction' => $transaction,
            ];
        } catch (\Throwable $th) {
            return [
                'success' => false,
                'message' => (defined('WP_DEBUG') && WP_DEBUG) ? $th->getMessage() : __('An error occurred', 'licenzo'),
            ];
        }
    }

    /**
     * v1.0.0 API parity stub.
     *
     * Freeze response shape identical to 1.0.0 release so any third-party
     * integration that polled this endpoint on a 1.0.0 install does not break
     * on upgrade. Plan change with proration is out of scope for v1.1.0
     * (ref: ADR-034 — plan-change subsystem removed; ADR-040 — v1.0.0 parity).
     *
     * @param int|string $id
     * @param Request $request
     * @return array
     */
    public function changePlan($id, Request $request)
    {
        return [
            'success' => false,
            'message' => __('Plan change with proration is coming soon.', 'licenzo'),
            'status'  => 403,
        ];
    }

    /**
     * v1.0.0 API parity stub.
     *
     * @see self::changePlan()
     *
     * @param int|string $id
     * @return array
     */
    public function applyPendingChanges($id)
    {
        return [
            'success' => false,
            'message' => __('Plan change with proration is coming soon.', 'licenzo'),
            'status'  => 403,
        ];
    }

    public function destroy($id)
    {
        try {
            $subscription = Subscription::find($id);

            if (!$subscription) {
                return [
                    'success' => false,
                    'message' => __('Subscription not found.', 'licenzo'),
                    'status'  => 404,
                ];
            }

            if ($subscription->status === 'active') {
                return [
                    'success' => false,
                    'message' => __('Cannot delete an active subscription. Cancel it first.', 'licenzo'),
                    'status'  => 422,
                ];
            }

            $subscription->licenses()->each(function ($license) {
                $license->activations()->delete();
                $license->licenseProducts()->delete();
                $license->events()->delete();
                $license->delete();
            });

            $subscription->subscriptionProducts()->delete();
            $subscription->transactions()->delete();
            $subscription->events()->delete();
            $subscription->schedules()->delete();
            $subscription->meta()->delete();
            $subscription->invoices()->each(function ($invoice) {
                $invoice->items()->delete();
                $invoice->delete();
            });
            $subscription->delete();

            return [
                'success' => true,
                'message' => __('Subscription deleted successfully.', 'licenzo'),
            ];
        } catch (\Throwable $th) {
            return [
                'success' => false,
                'message' => (defined('WP_DEBUG') && WP_DEBUG) ? $th->getMessage() : __('An error occurred', 'licenzo'),
                'status'  => 500,
            ];
        }
    }

    public function allSubscriptions(Request $request)
    {
        $search = $request->getSafe('search', 'sanitize_text_field');
        $customerId = $request->getSafe('customer_id', 'absint');
        global $wpdb;
        $escapedSearch = $search ? $wpdb->esc_like($search) : '';
        $subscriptions = Subscription::with(['customer', 'subscriptionProducts'])
            ->when($customerId, fn($query) => $query->where('customer_id', $customerId))
            ->when($escapedSearch, fn($query) => $query->where(function ($q) use ($escapedSearch) {
                $q->where('subscription_name', 'like', "%{$escapedSearch}%")
                    ->orWhereHas(
                        'customer',
                        fn($customerQuery) => $customerQuery->where('first_name', 'like', "%{$escapedSearch}%")
                            ->orWhere('last_name', 'like', "%{$escapedSearch}%")
                            ->orWhere('email', 'like', "%{$escapedSearch}%")
                    );
            }))
            ->orderBy('created_at', 'desc')
            ->limit(20)
            ->get();

        return [
            'success'       => true,
            'subscriptions' => $subscriptions
        ];
    }
}
