<?php

namespace WooNooW\Api\Controllers;

use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;
use WooNooW\Core\ModuleRegistry;

class AffiliateAdminController
{
    private $namespace = 'woonoow/v1';

    public function register_routes()
    {
        // List Affiliates
        register_rest_route($this->namespace, '/admin/affiliates', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_affiliates'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        // Get Affiliate Balance (payable amount)
        register_rest_route($this->namespace, '/admin/affiliates/(?P<id>\d+)/balance', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_affiliate_balance'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        // Approve Affiliate
        register_rest_route($this->namespace, '/admin/affiliates/(?P<id>\d+)/approve', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'approve_affiliate'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        // Update Affiliate (commission rate)
        register_rest_route($this->namespace, '/admin/affiliates/(?P<id>\d+)/update', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'update_affiliate'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        // List Referrals
        register_rest_route($this->namespace, '/admin/affiliates/referrals', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_referrals'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        // List Payouts (for all affiliates)
        register_rest_route($this->namespace, '/admin/affiliates/payouts', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_payouts'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        // Create Payout
        register_rest_route($this->namespace, '/admin/affiliates/payouts', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'create_payout'],
            'permission_callback' => [$this, 'check_permission'],
        ]);
    }

    public function check_permission()
    {
        return current_user_can('manage_woocommerce');
    }

    public function get_affiliates(WP_REST_Request $request)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'woonoow_affiliates';
        $affiliates = $wpdb->get_results("SELECT * FROM $table ORDER BY created_at DESC", ARRAY_A);

        // Add payable_balance to each affiliate
        foreach ($affiliates as &$affiliate) {
            $affiliate['payable_balance'] = (float) ($affiliate['total_earnings'] ?? 0) - (float) ($affiliate['paid_earnings'] ?? 0);
            // Get user info
            $user = get_userdata($affiliate['user_id']);
            if ($user) {
                $affiliate['user_email'] = $user->user_email;
                $affiliate['user_name'] = $user->display_name;
            }
        }

        return rest_ensure_response($affiliates);
    }

    public function get_affiliate_balance(WP_REST_Request $request)
    {
        global $wpdb;
        $id = $request->get_param('id');
        $table = $wpdb->prefix . 'woonoow_affiliates';

        $affiliate = $wpdb->get_row($wpdb->prepare(
            "SELECT id, user_id, referral_code, total_earnings, paid_earnings, total_referrals
             FROM $table WHERE id = %d",
            $id
        ));

        if (!$affiliate) {
            return new WP_REST_Response(['error' => 'Affiliate not found'], 404);
        }

        $user = get_userdata($affiliate->user_id);

        return rest_ensure_response([
            'id' => (int) $affiliate->id,
            'user_id' => (int) $affiliate->user_id,
            'user_name' => $user ? $user->display_name : 'Unknown',
            'user_email' => $user ? $user->user_email : '',
            'referral_code' => $affiliate->referral_code,
            'total_earnings' => (float) $affiliate->total_earnings,
            'paid_earnings' => (float) $affiliate->paid_earnings,
            'payable_balance' => (float) $affiliate->total_earnings - (float) $affiliate->paid_earnings,
            'total_referrals' => (int) $affiliate->total_referrals,
            'approved_referrals' => $this->get_approved_referral_count($affiliate->id),
            'pending_referrals' => $this->get_pending_referral_count($affiliate->id),
        ]);
    }

    private function get_approved_referral_count($affiliate_id)
    {
        global $wpdb;
        return (int) $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->prefix}woonoow_referrals WHERE affiliate_id = %d AND status = 'approved'",
            $affiliate_id
        ));
    }

    private function get_pending_referral_count($affiliate_id)
    {
        global $wpdb;
        return (int) $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->prefix}woonoow_referrals WHERE affiliate_id = %d AND status = 'pending'",
            $affiliate_id
        ));
    }

    public function approve_affiliate(WP_REST_Request $request)
    {
        global $wpdb;
        $id = $request->get_param('id');
        $table = $wpdb->prefix . 'woonoow_affiliates';

        $wpdb->update(
            $table,
            ['status' => 'active'],
            ['id' => $id]
        );

        // Trigger email notification for approval
        $affiliate = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE id = %d", $id));
        if ($affiliate) {
            $user = get_userdata($affiliate->user_id);
            if ($user) {
                do_action('woonoow/email/trigger', 'affiliate_application_approved', $user->user_email, [
                    'affiliate_name' => $user->display_name,
                    'referral_code' => $affiliate->referral_code
                ]);
            }
        }

        return rest_ensure_response(['success' => true]);
    }

    public function update_affiliate(WP_REST_Request $request)
    {
        global $wpdb;
        $id = $request->get_param('id');
        $table = $wpdb->prefix . 'woonoow_affiliates';

        $custom_rate = $request->get_param('custom_commission_rate');

        // If rate is empty string or not provided, clear custom rate
        if ($custom_rate === '' || $custom_rate === null || $custom_rate === false) {
            $data = ['custom_commission_rate' => null];
        } else {
            $custom_rate = floatval($custom_rate);
            if ($custom_rate < 0 || $custom_rate > 100) {
                return new WP_REST_Response(['error' => 'Commission rate must be between 0 and 100'], 400);
            }
            $data = ['custom_commission_rate' => $custom_rate];
        }

        $result = $wpdb->update(
            $table,
            $data,
            ['id' => $id]
        );

        if ($result === false) {
            return new WP_REST_Response(['error' => 'Failed to update affiliate'], 500);
        }

        return rest_ensure_response(['success' => true, 'custom_commission_rate' => $data['custom_commission_rate']]);
    }

    public function get_referrals(WP_REST_Request $request)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'woonoow_referrals';

        // Add filter support
        $where = "1=1";

        $affiliate_id = $request->get_param('affiliate_id');
        if ($affiliate_id) {
            $where .= $wpdb->prepare(" AND affiliate_id = %d", $affiliate_id);
        }

        $status = $request->get_param('status');
        if ($status) {
            $where .= $wpdb->prepare(" AND status = %s", $status);
        }

        $date_start = $request->get_param('date_start');
        if ($date_start) {
            $where .= $wpdb->prepare(" AND created_at >= %s", $date_start . ' 00:00:00');
        }

        $date_end = $request->get_param('date_end');
        if ($date_end) {
            $where .= $wpdb->prepare(" AND created_at <= %s", $date_end . ' 23:59:59');
        }

        $order_id = $request->get_param('order_id');
        if ($order_id) {
            $where .= $wpdb->prepare(" AND order_id = %d", $order_id);
        }

        $referrals = $wpdb->get_results("SELECT * FROM $table WHERE $where ORDER BY created_at DESC", ARRAY_A);

        // Enrich with affiliate info
        $affiliates_table = $wpdb->prefix . 'woonoow_affiliates';
        foreach ($referrals as &$referral) {
            $affiliate = $wpdb->get_row($wpdb->prepare(
                "SELECT a.*, u.display_name as affiliate_name, u.user_email as affiliate_email
                 FROM $affiliates_table a
                 LEFT JOIN $wpdb->users u ON a.user_id = u.ID
                 WHERE a.id = %d",
                $referral['affiliate_id']
            ));
            if ($affiliate) {
                $referral['affiliate_name'] = $affiliate->affiliate_name;
                $referral['affiliate_email'] = $affiliate->affiliate_email;
            }
        }

        return rest_ensure_response($referrals);
    }

    public function get_payouts(WP_REST_Request $request)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'woonoow_affiliate_payouts';

        $affiliate_id = $request->get_param('affiliate_id');
        $where = $affiliate_id ? $wpdb->prepare("WHERE affiliate_id = %d", $affiliate_id) : "";

        $payouts = $wpdb->get_results("SELECT * FROM $table $where ORDER BY created_at DESC", ARRAY_A);

        // Enrich with affiliate info
        $affiliates_table = $wpdb->prefix . 'woonoow_affiliates';
        foreach ($payouts as &$payout) {
            $affiliate = $wpdb->get_row($wpdb->prepare(
                "SELECT a.*, u.display_name as affiliate_name, u.user_email as affiliate_email
                 FROM $affiliates_table a
                 LEFT JOIN $wpdb->users u ON a.user_id = u.ID
                 WHERE a.id = %d",
                $payout['affiliate_id']
            ));
            if ($affiliate) {
                $payout['affiliate_name'] = $affiliate->affiliate_name;
                $payout['affiliate_email'] = $affiliate->affiliate_email;
            }
        }

        return rest_ensure_response($payouts);
    }

    public function create_payout(WP_REST_Request $request)
    {
        global $wpdb;
        $payouts_table = $wpdb->prefix . 'woonoow_affiliate_payouts';
        $affiliates_table = $wpdb->prefix . 'woonoow_affiliates';

        $affiliate_id = absint($request->get_param('affiliate_id'));
        $amount = floatval($request->get_param('amount'));
        $method = sanitize_text_field($request->get_param('method') ?: 'bank_transfer');
        $notes = '';

        // Validate affiliate exists and get balance
        $affiliate = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM $affiliates_table WHERE id = %d",
            $affiliate_id
        ));

        if (!$affiliate) {
            return new WP_REST_Response(['error' => 'Affiliate not found'], 404);
        }

        $payable_balance = (float) $affiliate->total_earnings - (float) $affiliate->paid_earnings;

        if ($amount <= 0) {
            return new WP_REST_Response(['error' => 'Amount must be greater than 0'], 400);
        }

        if ($amount > $payable_balance) {
            return new WP_REST_Response([
                'error' => 'Amount exceeds payable balance',
                'payable_balance' => $payable_balance
            ], 400);
        }

        // Generate coupon for store_credit method
        if ($method === 'store_credit') {
            $user = get_userdata($affiliate->user_id);
            if ($user) {
                $coupon_code = 'CREDIT-' . strtoupper(wp_generate_password(8, false));
                $coupon = new \WC_Coupon();
                $coupon->set_code($coupon_code);
                $coupon->set_discount_type('fixed_cart');
                $coupon->set_amount($amount);
                $coupon->set_email_restrictions([$user->user_email]);
                $coupon->set_usage_limit(1);
                $coupon->set_description('Store Credit for Affiliate Payout');
                $coupon->save();

                $notes = 'Generated Store Credit Coupon: ' . $coupon_code;
            }
        }

        // Create payout record
        $wpdb->insert($payouts_table, [
            'affiliate_id' => $affiliate_id,
            'amount' => $amount,
            'currency' => get_woocommerce_currency(),
            'method' => $method,
            'status' => 'completed',
            'notes' => $notes,
            'completed_at' => current_time('mysql')
        ]);

        $payout_id = $wpdb->insert_id;

        // Update affiliate's paid_earnings
        $wpdb->query($wpdb->prepare(
            "UPDATE $affiliates_table SET paid_earnings = paid_earnings + %f WHERE id = %d",
            $amount,
            $affiliate_id
        ));

        return rest_ensure_response([
            'success' => true,
            'id' => $payout_id,
            'new_paid_earnings' => (float) $affiliate->paid_earnings + $amount,
            'new_payable_balance' => $payable_balance - $amount,
            'coupon_code' => $method === 'store_credit' ? $coupon_code : null
        ]);
    }
}
