<?php

namespace MtcPharmacy\ReferAFriend\Http\Controllers\Admin;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\DB;
use Mtc\Modules\Members\Models\Member;
use Mtc\Shop\Coupon;
use MtcPharmacy\ReferAFriend\Models\Referral;
use MtcPharmacy\ReferAFriend\Models\ReferralActivityLog;
use MtcPharmacy\ReferAFriend\Models\ReferralReward;

class ReferralsAdminController extends Controller
{
    public function dashboard(Request $request)
    {
        // Stats
        $totalReferrals = Referral::count();
        $rewardedCount = Referral::where('status', 'rewarded')->count();
        $conversionRate = $totalReferrals > 0 ? round(($rewardedCount / $totalReferrals) * 100, 1) : 0;
        $totalRewardsValue = ReferralReward::whereIn('status', ['issued', 'redeemed'])->sum('amount');
        $pendingCount = Referral::where('status', 'pending')->count();
        $flaggedCount = ReferralActivityLog::where('action', 'fraud_flagged')->distinct('referral_id')->count('referral_id');

        // Build referrals query with filters
        $query = Referral::with(['referrer', 'referee'])
            ->orderBy('created_at', 'desc');

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

        if ($request->filled('date_from')) {
            $query->where('created_at', '>=', $request->input('date_from'));
        }

        if ($request->filled('date_to')) {
            $query->where('created_at', '<=', $request->input('date_to') . ' 23:59:59');
        }

        if ($request->filled('flagged')) {
            $flaggedIds = ReferralActivityLog::where('action', 'fraud_flagged')
                ->pluck('referral_id')
                ->unique();
            $query->whereIn('id', $flaggedIds);
        }

        $referrals = $query->paginate(25);

        return template('admin/referrals/dashboard.twig', [
            'total_referrals'     => $totalReferrals,
            'conversion_rate'     => $conversionRate,
            'total_rewards_value' => $totalRewardsValue,
            'pending_count'       => $pendingCount,
            'flagged_count'       => $flaggedCount,
            'referrals'           => $referrals,
            'filters'             => $request->only(['status', 'date_from', 'date_to', 'flagged']),
            'page_title'          => 'Referral Program',
            'success_message'     => session('success'),
            'error_message'       => session('error'),
        ]);
    }

    public function detail(Request $request, int $id)
    {
        $referral = Referral::with(['referrer', 'referee', 'rewards', 'activityLog' => function ($q) {
            $q->orderBy('created_at', 'desc');
        }])->findOrFail($id);

        return template('admin/referrals/detail.twig', [
            'referral'        => $referral,
            'page_title'      => 'Referral Detail #' . $id,
            'success_message' => session('success'),
            'error_message'   => session('error'),
        ]);
    }

    public function manualCredit(Request $request)
    {
        $request->validate([
            'member_id' => 'required|integer|exists:members,id',
            'amount'    => 'required|numeric|min:0.01|max:' . config('referrals.max_manual_credit'),
            'reason'    => 'required|string|max:255',
        ]);

        $memberId = $request->input('member_id');
        $amount = (float) $request->input('amount', config('referrals.reward_amount'));
        $reason = $request->input('reason');

        $member = Member::findOrFail($memberId);
        $adminId = session('admin_id', null);

        DB::transaction(function () use ($member, $amount, $reason, $adminId, $request) {
            $coupon = Coupon::generateCoupon([
                'prefix'      => config('referrals.coupon_prefix'),
                'type'        => 'single',
                'value'       => $amount,
                'min_price'   => config('referrals.coupon_min_spend'),
                'redemptions' => 1,
                'name'        => 'Refer a Friend - Manual Credit',
                'exp_date'    => now()->addDays(config('referrals.coupon_expiry_days'))->format('Y-m-d'),
            ]);

            ReferralReward::create([
                'referral_id' => null,
                'member_id'   => $member->id,
                'type'        => 'referrer',
                'coupon_id'   => $coupon->id,
                'coupon_code' => $coupon->code,
                'amount'      => $amount,
                'status'      => 'issued',
                'issued_at'   => now(),
                'admin_id'    => $adminId,
            ]);

            ReferralActivityLog::create([
                'referral_id' => null,
                'member_id'   => $member->id,
                'action'      => 'reward_issued',
                'details'     => json_encode([
                    'type'   => 'manual_credit',
                    'reason' => $reason,
                    'amount' => $amount,
                    'admin'  => $adminId,
                ]),
                'ip_address'  => $request->ip(),
                'created_at'  => now(),
            ]);
        });

        return redirect('/admin/referrals')->with('success', 'Manual credit issued to ' . $member->email);
    }

    public function revokeReward(Request $request, int $id)
    {
        $reward = ReferralReward::findOrFail($id);
        $reason = $request->input('reason');

        if (!$reason) {
            return redirect()->back()->with('error', 'Reason is required to revoke a reward.');
        }

        $adminId = session('admin_id', null);

        DB::transaction(function () use ($reward, $reason, $adminId, $request) {
            if ($reward->coupon_id) {
                $coupon = Coupon::find($reward->coupon_id);
                if ($coupon) {
                    $coupon->redemptions = 0;
                    $coupon->save();
                }
            }

            $reward->update([
                'status'        => 'revoked',
                'revoked_at'    => now(),
                'revoke_reason' => $reason,
                'admin_id'      => $adminId,
            ]);

            ReferralActivityLog::create([
                'referral_id' => $reward->referral_id,
                'member_id'   => $reward->member_id,
                'action'      => 'reward_revoked',
                'details'     => json_encode([
                    'reason' => $reason,
                    'admin'  => $adminId,
                ]),
                'ip_address'  => $request->ip(),
                'created_at'  => now(),
            ]);
        });

        $redirectUrl = $reward->referral_id
            ? '/admin/referrals/detail/' . $reward->referral_id
            : '/admin/referrals';

        return redirect($redirectUrl)->with('success', 'Reward revoked.');
    }

    public function emails()
    {
        $twig = app('twig');

        return $twig->render('admin/referrals/emails.twig');
    }

    private function sanitizeCsvValue(?string $value): string
    {
        $value = $value ?? '';
        if ($value !== '' && in_array(mb_substr($value, 0, 1), ['=', '+', '-', '@', "\t", "\r"])) {
            return "'" . $value;
        }
        return $value;
    }

    public function export(Request $request)
    {
        $query = Referral::with(['referrer', 'referee', 'rewards', 'qualifyingOrder'])
            ->orderBy('created_at', 'desc');

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

        if ($request->filled('date_from')) {
            $query->where('created_at', '>=', $request->input('date_from'));
        }

        if ($request->filled('date_to')) {
            $query->where('created_at', '<=', $request->input('date_to') . ' 23:59:59');
        }

        if ($request->filled('flagged')) {
            $flaggedIds = ReferralActivityLog::where('action', 'fraud_flagged')
                ->pluck('referral_id')
                ->unique();
            $query->whereIn('id', $flaggedIds);
        }

        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="referrals-export-' . date('Y-m-d') . '.csv"',
        ];

        return response()->stream(function () use ($query) {
            $handle = fopen('php://output', 'w');

            fputcsv($handle, [
                'Referral ID',
                'Referrer Email',
                'Referee Email',
                'Status',
                'Channel',
                'Order ID',
                'Order Value',
                'Reward Amount',
                'Reward Status',
                'Date',
            ]);

            $query->chunkById(100, function ($referrals) use ($handle) {
                foreach ($referrals as $referral) {
                    $reward = $referral->rewards->first();
                    $orderValue = $referral->qualifyingOrder
                        ? ($referral->qualifyingOrder->cost_total ?? '')
                        : '';

                    fputcsv($handle, [
                        $referral->id,
                        $this->sanitizeCsvValue($referral->referrer->email ?? ''),
                        $this->sanitizeCsvValue($referral->referee_email),
                        $referral->status,
                        $referral->channel,
                        $referral->qualifying_order_id ?? '',
                        $orderValue,
                        $reward->amount ?? '',
                        $reward->status ?? '',
                        $referral->created_at->format('Y-m-d H:i'),
                    ]);
                }
            });

            fclose($handle);
        }, 200, $headers);
    }
}
