<?php

namespace App\Http\Controllers\Finance;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Transaction;
use App\Models\FinanceGroup;
use App\Models\CannedResponse;
use App\Models\ActivityLog;
use App\Models\Site;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
use App\Support\BusinessTime;
use App\Services\PayGarantiService;
use App\Support\SiteCredentialResolver;

class WithdrawalController extends Controller
{
    public function index(Request $request)
    {
        $user = auth()->guard('finance')->user();
        $financeGroupId = $user->finance_group_id;

        $query = Transaction::withdrawals()
            ->with(['financeGroup', 'bankAccount', 'approvedBy', 'site'])
            ->where('finance_group_id', $financeGroupId);
        $forcedSite = null;
        $routeSite = $request->route('site');
        if ($routeSite === null && $request->segment(2) === 'sites' && $request->segment(4) === 'withdrawals') {
            $routeSite = $request->segment(3);
        }
        if ($routeSite !== null) {
            if ($routeSite instanceof Site) {
                $forcedSite = $routeSite;
            } elseif (is_numeric($routeSite)) {
                $forcedSite = Site::find((int) $routeSite);
            } else {
                $forcedSite = Site::where('sid', (string) $routeSite)->first();
            }

            if (!$forcedSite) {
                abort(404);
            }
        }

        $isSiteScoped = $forcedSite !== null;
        $forcedSiteId = $forcedSite ? (int) $forcedSite->id : null;
        $siteFilterId = $forcedSite
            ? (int) $forcedSite->id
            : ($request->filled('site_id') ? (int) $request->site_id : null);

        if ($siteFilterId) {
            SiteCredentialResolver::applySiteFilter($query, $siteFilterId);
        }

        if ($request->filled('status')) {
            if ($request->status === 'approved') {
                $query->whereIn('status', ['approved', 'completed']);
            } elseif ($request->status === 'declined') {
                $query->whereIn('status', ['declined', 'failed']);
            } else {
                $query->where('status', $request->status);
            }
        }
        $dateMode = $request->input('date_mode', 'gaming');
        if ($request->filled('date_from') || $request->filled('date_to')) {
            $fromInput = $request->filled('date_from') ? $request->date_from : $request->date_to;
            $toInput = $request->filled('date_to') ? $request->date_to : $request->date_from;
            $fromHasTime = is_string($fromInput) && preg_match('/\d{2}:\d{2}/', $fromInput);
            $toHasTime = is_string($toInput) && preg_match('/\d{2}:\d{2}/', $toInput);
            if ($dateMode === 'actual') {
                $rangeFrom = $fromHasTime
                    ? Carbon::parse($fromInput, BusinessTime::timezone())
                    : Carbon::parse($fromInput, BusinessTime::timezone())->startOfDay();
                $rangeTo = $toHasTime
                    ? Carbon::parse($toInput, BusinessTime::timezone())
                    : Carbon::parse($toInput, BusinessTime::timezone())->endOfDay();
            } else {
                $rangeFrom = $fromHasTime
                    ? Carbon::parse($fromInput, BusinessTime::timezone())
                    : BusinessTime::startOfBusinessDay(Carbon::parse($fromInput, BusinessTime::timezone())->format('Y-m-d'));
                $rangeTo = $toHasTime
                    ? Carbon::parse($toInput, BusinessTime::timezone())
                    : BusinessTime::endOfBusinessDay(Carbon::parse($toInput, BusinessTime::timezone())->format('Y-m-d'));
            }
        } else {
            if ($dateMode === 'actual') {
                $rangeTo = Carbon::now(BusinessTime::timezone());
                $rangeFrom = (clone $rangeTo)->subHours(24);
            } else {
                $businessDate = BusinessTime::currentBusinessDate()->format('Y-m-d');
                $rangeFrom = BusinessTime::startOfBusinessDay($businessDate);
                $rangeTo = BusinessTime::endOfBusinessDay($businessDate);
            }
        }
        $query->whereBetween('created_at', [$rangeFrom, $rangeTo]);

        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('transaction_id', 'like', "%{$search}%")
                    ->orWhere('customer_name', 'like', "%{$search}%")
                    ->orWhere('customer_tc', 'like', "%{$search}%")
                    ->orWhere('customer_iban', 'like', "%{$search}%");
            });
        }

        if ($request->ajax()) {
            $withdrawals = $query->orderBy('created_at', 'desc')->get();
            $sites = Site::all();

            return response()->json([
                'data' => $withdrawals->map(function ($transaction) use ($sites) {
                    $resolvedSite = SiteCredentialResolver::resolveForTransaction($transaction, $sites);
                    return [
                        'id' => $transaction->id,
                        'transaction_id' => $transaction->transaction_id,
                        'status' => $transaction->status,
                        'amount' => number_format($transaction->amount, 2),
                        'currency' => $transaction->currency,
                        'customer_name' => $transaction->customer_name,
                        'customer_account_holder' => $transaction->customer_account_holder,
                        'customer_iban' => $transaction->customer_iban,
                        'customer_bank_name' => $transaction->customer_bank_name,
                        'source' => $transaction->source ?? 'auto',
                        'created_by_name' => $transaction->created_by_name,
                        'site_id' => $resolvedSite ? $resolvedSite->id : null,
                        'site_name' => $resolvedSite ? $resolvedSite->name : '-',
                        'description' => $transaction->description,
                        'bank_account' => $transaction->bankAccount ? $transaction->bankAccount->account_name : '-',
                        'bank_account_iban' => $transaction->bankAccount ? $transaction->bankAccount->iban : null,
                        'created_at' => $transaction->created_at->format('d.m.Y H:i'),
                        'created_at_timestamp' => $transaction->created_at->timestamp,
                        'actions' => true,
                    ];
                })
            ]);
        }

        $financeGroup = FinanceGroup::findOrFail($financeGroupId);

        $confirmedStatuses = ['approved', 'completed'];
        $declinedStatuses = ['declined', 'failed'];

        $statsQuery = Transaction::withdrawals()
            ->where('finance_group_id', $financeGroupId)
            ->whereBetween('created_at', [$rangeFrom, $rangeTo]);
        if ($siteFilterId) {
            SiteCredentialResolver::applySiteFilter($statsQuery, $siteFilterId);
        }

        $stats = [
            'total' => (clone $statsQuery)->count(),
            'pending' => (clone $statsQuery)->pending()->count(),
            'approved' => (clone $statsQuery)->whereIn('status', $confirmedStatuses)->count(),
            'declined' => (clone $statsQuery)->whereIn('status', $declinedStatuses)->count(),
            'total_amount' => (clone $statsQuery)->whereIn('status', $confirmedStatuses)->sum('amount'),
        ];

        $cannedResponses = CannedResponse::orderBy('id', 'desc')->get();

        return view('finance.withdrawals.index', compact('financeGroup', 'stats', 'cannedResponses', 'forcedSite', 'isSiteScoped', 'forcedSiteId'));
    }

    public function store(Request $request)
    {
        $user = auth()->guard('finance')->user();
        $financeGroupId = $user->finance_group_id;

        $request->validate([
            'customer_name' => 'required|string|max:255',
            'customer_email' => 'nullable|email',
            'amount' => 'required|numeric|min:1',
            'site_id' => 'nullable|exists:sites,id',
            'finance_group_id' => 'required|exists:finance_groups,id',
            'iban' => 'required|string',
            'account_holder' => 'nullable|string|max:255',
            'bank_name' => 'nullable|string|max:255',
            'description' => 'nullable|string|max:1000',
            'notes' => 'nullable|string',
        ], [
            'customer_name.required' => 'Müşteri adı gereklidir.',
            'amount.required' => 'Tutar gereklidir.',
            'amount.min' => 'Tutar 0\'dan büyük olmalıdır.',
            'finance_group_id.required' => 'Finans grubu seçilmelidir.',
            'finance_group_id.exists' => 'Geçersiz finans grubu.',
            'iban.required' => 'IBAN gereklidir.',
        ]);

        if ((int) $request->finance_group_id !== (int) $financeGroupId) {
            return response()->json([
                'success' => false,
                'message' => 'Geçersiz finans grubu.',
            ], 403);
        }

        DB::beginTransaction();
        try {
            $site = null;
            if ($request->filled('site_id')) {
                $site = Site::findOrFail((int) $request->site_id);
                if (!$site->is_active) {
                    return response()->json([
                        'success' => false,
                        'message' => 'Secilen site pasif durumda.',
                    ], 422);
                }
            }

            $transactionId = Transaction::generateUniqueTransactionId('W');

            $transaction = Transaction::create([
                'transaction_id' => $transactionId,
                'type' => 'withdrawal',
                'source' => 'manual',
                'status' => 'pending',
                'amount' => $request->amount,
                'currency' => 'TRY',
                'site_id' => $site ? $site->id : null,
                'sid' => $site ? $site->sid : null,
                'api_key' => $site ? $site->api_key : null,
                'customer_name' => $request->customer_name,
                'customer_email' => $request->customer_email,
                'customer_iban' => $request->iban,
                'customer_bank_name' => $request->bank_name,
                'customer_account_holder' => $request->account_holder,
                'finance_group_id' => $financeGroupId,
                'ip_address' => $request->ip(),
                'description' => $request->description,
                'notes' => $request->notes,
                'created_by_name' => auth()->guard('finance')->user()->full_name ?? auth()->guard('finance')->user()->name ?? null,
            ]);

            ActivityLog::log(
                'create_withdrawal',
                'withdrawals',
                "Yeni çekim oluşturuldu: {$transaction->transaction_id} - {$transaction->customer_name} - " . number_format($transaction->amount, 2) . " TRY",
                null,
                $transaction->toArray()
            );

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Çekim başarıyla oluşturuldu.',
                'transaction' => $transaction,
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => 'Çekim oluşturulurken bir hata oluştu: ' . $e->getMessage(),
            ], 500);
        }
    }

    public function show($id)
    {
        $user = auth()->guard('finance')->user();
        $withdrawal = Transaction::withdrawals()
            ->with(['financeGroup', 'bankAccount', 'approvedBy', 'site'])
            ->where('finance_group_id', $user->finance_group_id)
            ->findOrFail($id);
        $withdrawal->setAttribute('created_at_display', BusinessTime::businessDateTime($withdrawal->created_at)->format('d.m.Y H:i'));
        $withdrawal->setAttribute('site_name', optional(SiteCredentialResolver::resolveForTransaction($withdrawal))->name);

        return response()->json([
            'success' => true,
            'transaction' => $withdrawal,
        ]);
    }

    public function approve(Request $request, $id)
    {
        $user = auth()->guard('finance')->user();
        $withdrawal = Transaction::withdrawals()
            ->where('finance_group_id', $user->finance_group_id)
            ->findOrFail($id);

        if ($withdrawal->status !== 'pending') {
            return response()->json([
                'success' => false,
                'message' => 'Bu çekim zaten işleme alınmış.',
            ], 400);
        }

        DB::beginTransaction();
        try {
            $oldStatus = $withdrawal->status;

            $withdrawal->update([
                'status' => 'approved',
                'approved_by_name' => auth()->guard('finance')->user()->full_name ?? auth()->guard('finance')->user()->name ?? null,
                'approved_at' => now(),
                'notes' => $request->notes,
            ]);

            ActivityLog::log(
                'approve_withdrawal',
                'withdrawals',
                "Çekim onaylandı: {$withdrawal->transaction_id}",
                ['status' => $oldStatus],
                ['status' => 'approved', 'notes' => $request->notes]
            );

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Çekim başarıyla onaylandı.',
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => 'Çekim onaylanırken bir hata oluştu: ' . $e->getMessage(),
            ], 500);
        }
    }

    public function decline(Request $request, $id)
    {
        $request->validate([
            'notes' => 'required|string|min:3',
        ], [
            'notes.required' => 'Red nedeni gereklidir.',
            'notes.min' => 'Red nedeni en az 3 karakter olmalıdır.',
        ]);

        $user = auth()->guard('finance')->user();
        $withdrawal = Transaction::withdrawals()
            ->where('finance_group_id', $user->finance_group_id)
            ->findOrFail($id);

        if ($withdrawal->status !== 'pending') {
            return response()->json([
                'success' => false,
                'message' => 'Bu çekim zaten işleme alınmış.',
            ], 400);
        }

        DB::beginTransaction();
        try {
            $oldStatus = $withdrawal->status;

            $withdrawal->update([
                'status' => 'declined',
                'approved_by_name' => auth()->guard('finance')->user()->full_name ?? auth()->guard('finance')->user()->name ?? null,
                'approved_at' => now(),
                'notes' => $request->notes,
            ]);

            ActivityLog::log(
                'decline_withdrawal',
                'withdrawals',
                "Çekim reddedildi: {$withdrawal->transaction_id}",
                ['status' => $oldStatus],
                ['status' => 'declined', 'notes' => $request->notes]
            );

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Çekim başarıyla reddedildi.',
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => 'Çekim reddedilirken bir hata oluştu: ' . $e->getMessage(),
            ], 500);
        }
    }

    public function complete(Request $request, $id)
    {
        $user = auth()->guard('finance')->user();
        $withdrawal = Transaction::withdrawals()
            ->where('finance_group_id', $user->finance_group_id)
            ->findOrFail($id);

        if ($withdrawal->status !== 'approved') {
            return response()->json([
                'success' => false,
                'message' => 'Sadece onaylanmış çekimler tamamlanabilir.',
            ], 400);
        }

        DB::beginTransaction();
        try {
            $oldStatus = $withdrawal->status;

            $withdrawal->update([
                'status' => 'completed',
                'notes' => $request->notes,
            ]);

            ActivityLog::log(
                'complete_withdrawal',
                'withdrawals',
                "Çekim tamamlandı: {$withdrawal->transaction_id}",
                ['status' => $oldStatus],
                ['status' => 'completed', 'notes' => $request->notes]
            );

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Çekim başarıyla tamamlandı.',
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => 'Çekim tamamlanırken bir hata oluştu: ' . $e->getMessage(),
            ], 500);
        }
    }

    public function stats(Request $request)
    {
        $user = auth()->guard('finance')->user();

        $query = Transaction::withdrawals()
            ->where('finance_group_id', $user->finance_group_id);
        if ($request->filled('site_id')) {
            SiteCredentialResolver::applySiteFilter($query, (int) $request->site_id);
        }
        $dateMode = $request->input('date_mode', 'gaming');
        if ($request->filled('date_from') || $request->filled('date_to')) {
            $fromInput = $request->filled('date_from') ? $request->date_from : $request->date_to;
            $toInput = $request->filled('date_to') ? $request->date_to : $request->date_from;
            $fromHasTime = is_string($fromInput) && preg_match('/\d{2}:\d{2}/', $fromInput);
            $toHasTime = is_string($toInput) && preg_match('/\d{2}:\d{2}/', $toInput);
            if ($dateMode === 'actual') {
                $rangeFrom = $fromHasTime
                    ? Carbon::parse($fromInput, BusinessTime::timezone())
                    : Carbon::parse($fromInput, BusinessTime::timezone())->startOfDay();
                $rangeTo = $toHasTime
                    ? Carbon::parse($toInput, BusinessTime::timezone())
                    : Carbon::parse($toInput, BusinessTime::timezone())->endOfDay();
            } else {
                $rangeFrom = $fromHasTime
                    ? Carbon::parse($fromInput, BusinessTime::timezone())
                    : BusinessTime::startOfBusinessDay(Carbon::parse($fromInput, BusinessTime::timezone())->format('Y-m-d'));
                $rangeTo = $toHasTime
                    ? Carbon::parse($toInput, BusinessTime::timezone())
                    : BusinessTime::endOfBusinessDay(Carbon::parse($toInput, BusinessTime::timezone())->format('Y-m-d'));
            }
        } else {
            if ($dateMode === 'actual') {
                $rangeTo = Carbon::now(BusinessTime::timezone());
                $rangeFrom = (clone $rangeTo)->subHours(24);
            } else {
                $businessDate = BusinessTime::currentBusinessDate()->format('Y-m-d');
                $rangeFrom = BusinessTime::startOfBusinessDay($businessDate);
                $rangeTo = BusinessTime::endOfBusinessDay($businessDate);
            }
        }
        $query->whereBetween('created_at', [$rangeFrom, $rangeTo]);

        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('transaction_id', 'like', "%{$search}%")
                    ->orWhere('customer_name', 'like', "%{$search}%")
                    ->orWhere('customer_tc', 'like', "%{$search}%")
                    ->orWhere('customer_iban', 'like', "%{$search}%");
            });
        }

        $confirmedStatuses = ['approved', 'completed'];
        $declinedStatuses = ['declined', 'failed'];

        return response()->json([
            'total' => (clone $query)->count(),
            'pending' => (clone $query)->where('status', 'pending')->count(),
            'approved' => (clone $query)->whereIn('status', $confirmedStatuses)->count(),
            'declined' => (clone $query)->whereIn('status', $declinedStatuses)->count(),
        ]);
    }

    public function checkNew(Request $request)
    {
        $since = $request->input('since');

        if (!$since || !is_numeric($since)) {
            return response()->json([
                'success' => false,
                'message' => 'Timestamp parametresi gerekli.',
            ], 400);
        }

        $sinceDate = Carbon::createFromTimestamp((int) $since);

        $user = auth()->guard('finance')->user();

        $baseQuery = Transaction::withdrawals()
            ->with('site')
            ->where('finance_group_id', $user->finance_group_id);
        if ($request->filled('site_id')) {
            SiteCredentialResolver::applySiteFilter($baseQuery, (int) $request->site_id);
        }

        $updatedCount = (clone $baseQuery)
            ->where('updated_at', '>', $sinceDate)
            ->count();

        $latestUpdate = (clone $baseQuery)->max('updated_at');
        $latestTimestamp = $latestUpdate ? Carbon::parse($latestUpdate)->timestamp : (int) $since;

        $newWithdrawals = (clone $baseQuery)
            ->pending()
            ->with(['financeGroup', 'bankAccount', 'approvedBy'])
            ->where('created_at', '>', $sinceDate)
            ->orderBy('created_at', 'desc')
            ->get()
            ->map(function ($transaction) {
                $resolvedSite = SiteCredentialResolver::resolveForTransaction($transaction);
                return [
                    'id' => $transaction->id,
                    'transaction_id' => $transaction->transaction_id,
                    'status' => $transaction->status,
                    'amount' => number_format($transaction->amount, 2),
                    'currency' => $transaction->currency,
                    'customer_name' => $transaction->customer_name,
                    'site_name' => $resolvedSite ? $resolvedSite->name : '-',
                    'customer_account_holder' => $transaction->customer_account_holder,
                    'customer_iban' => $transaction->customer_iban,
                    'customer_bank_name' => $transaction->customer_bank_name,
                    'bank_account' => $transaction->bankAccount ? $transaction->bankAccount->account_name : '-',
                    'created_at' => $transaction->created_at->format('d.m.Y H:i'),
                    'created_at_timestamp' => $transaction->created_at->timestamp,
                    'actions' => true,
                ];
            });

        return response()->json([
            'success' => true,
            'count' => $newWithdrawals->count(),
            'data' => $newWithdrawals,
            'updated_count' => $updatedCount,
            'latest_timestamp' => $latestTimestamp,
        ]);
    }
}
