<?php

namespace App\Http\Controllers\Finance;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\BankAccount;
use App\Models\BankAccountSiteStatus;
use App\Models\FinanceGroup;
use App\Models\Site;
use App\Models\ActivityLog;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class BankAccountController extends Controller
{
    public function index(Request $request)
    {
        $user = auth()->guard('finance')->user();
        $sites = Site::orderBy('name')->get(['id', 'name', 'is_active']);
        $forcedSite = null;
        $routeSite = $request->route('site');
        if ($routeSite === null && $request->segment(2) === 'sites' && $request->segment(4) === 'bank-accounts') {
            $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 = $forcedSiteId ?: ($request->filled('site_id') ? (int) $request->site_id : null);

        $hasBlockedColumn = Schema::hasColumn('bank_accounts', 'is_blocked');
        $showBlocked = $hasBlockedColumn ? $request->boolean('blocked', false) : false;

        $query = BankAccount::with(['financeGroup', 'creator'])
            ->with('siteStatuses')
            ->withCount('siteStatuses')
            ->withCount('transactions')
            ->where('finance_group_id', $user->finance_group_id);

        if ($hasBlockedColumn) {
            $query->where('is_blocked', $showBlocked);
        }

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

        if ($request->filled('is_active')) {
            $query->where('is_active', $request->is_active === '1');
        }

        if ($request->ajax()) {
            $accounts = $query->orderBy('created_at', 'desc')->get();
            $renderSites = $siteFilterId
                ? $sites->where('id', $siteFilterId)->values()
                : $sites;
            $countsQuery = BankAccount::query()->where('finance_group_id', $user->finance_group_id);
            if ($request->filled('finance_group_id')) {
                $countsQuery->where('finance_group_id', $request->finance_group_id);
            }
            $activeCount = $hasBlockedColumn
                ? (clone $countsQuery)->where('is_blocked', false)->count()
                : (clone $countsQuery)->count();
            $blockedCount = $hasBlockedColumn
                ? (clone $countsQuery)->where('is_blocked', true)->count()
                : 0;

            return response()->json([
                'data' => $accounts->map(function ($account) use ($renderSites) {
                    $isBlocked = (bool) ($account->is_blocked ?? false);
                    $statusBySiteId = $account->siteStatuses->keyBy('site_id');
                    $siteStatuses = $renderSites->map(function (Site $site) use ($account, $statusBySiteId, $isBlocked) {
                        if ($isBlocked) {
                            return [
                                'site_id' => (int) $site->id,
                                'site_name' => $site->name,
                                'site_is_active' => (bool) $site->is_active,
                                'is_active' => false,
                                'source' => 'blocked',
                            ];
                        }

                        $hasOverride = $statusBySiteId->has($site->id);
                        $effectiveActive = $hasOverride
                            ? (bool) $statusBySiteId->get($site->id)->is_active
                            : (bool) $account->is_active;

                        return [
                            'site_id' => (int) $site->id,
                            'site_name' => $site->name,
                            'site_is_active' => (bool) $site->is_active,
                            'is_active' => $effectiveActive,
                            'source' => $hasOverride ? 'override' : 'default',
                        ];
                    })->values();

                    return [
                        'id' => $account->id,
                        'bank_name' => $account->bank_name,
                        'account_holder' => $account->account_holder,
                        'iban' => $account->iban,
                        'transactions_count' => $account->transactions_count ?? 0,
                        'min_amount' => (float) $account->min_amount,
                        'max_amount' => (float) $account->max_amount,
                        'is_active' => $account->is_active,
                        'is_blocked' => $isBlocked,
                        'site_overrides_count' => (int) ($account->site_statuses_count ?? 0),
                        'site_statuses' => $siteStatuses,
                        'created_by_name' => $account->creator ? $account->creator->full_name : '-',
                        'created_at' => $account->created_at->format('d.m.Y H:i'),
                    ];
                }),
                'counts' => [
                    'active' => $activeCount,
                    'blocked' => $blockedCount,
                ],
            ]);
        }

        $financeGroup = FinanceGroup::findOrFail($user->finance_group_id);

        return view('finance.bank-accounts.index', compact('financeGroup', 'forcedSite', 'isSiteScoped', 'forcedSiteId'));
    }

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

        $request->validate([
            'finance_group_id' => 'required|exists:finance_groups,id',
            'bank_name' => 'required|string|max:255',
            'account_holder' => 'required|string|max:255',
            'iban' => 'required|string|max:34',
            'description' => 'nullable|string|max:255',
            'min_amount' => 'required|numeric|min:0',
            'max_amount' => 'required|numeric|gt:min_amount',
            'is_active' => 'boolean',
        ], [
            'finance_group_id.required' => 'Finans grubu seçilmelidir.',
            'finance_group_id.exists' => 'Geçersiz finans grubu.',
            'bank_name.required' => 'Banka adı gereklidir.',
            'account_holder.required' => 'Hesap sahibi gereklidir.',
            'iban.required' => 'IBAN gereklidir.',
            'min_amount.required' => 'Minimum tutar gereklidir.',
            'max_amount.required' => 'Maximum tutar gereklidir.',
            'max_amount.gt' => 'Maximum tutar minimum tutardan büyük olmalıdır.',
        ]);

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

        $hasDescriptionColumn = Schema::hasColumn('bank_accounts', 'description');
        if ($request->filled('description') && !$hasDescriptionColumn) {
            return response()->json([
                'success' => false,
                'message' => 'Aciklama alani kaydedilemiyor. Lutfen once veritabanini guncelleyin (description kolonu eksik).',
            ], 500);
        }

        DB::beginTransaction();
        try {
            $payload = [
                'finance_user_id' => $user->id,
                'finance_group_id' => $financeGroupId,
                'bank_name' => $request->bank_name,
                'account_holder_name' => $request->account_holder,
                'account_name' => $request->account_holder,
                'iban' => $request->iban,
                'min_amount' => $request->min_amount,
                'max_amount' => $request->max_amount,
                'is_active' => $request->boolean('is_active', true),
                'created_by' => null,
            ];

            if (Schema::hasColumn('bank_accounts', 'is_blocked')) {
                $payload['is_blocked'] = false;
            }

            if ($hasDescriptionColumn) {
                $payload['description'] = $request->description;
            }

            if (Schema::hasColumn('bank_accounts', 'account_holder')) {
                $payload['account_holder'] = $request->account_holder;
            }

            $account = BankAccount::create($payload);

            ActivityLog::log(
                'create_bank_account',
                'bank_accounts',
                "Banka hesabı oluşturuldu: {$account->account_name}",
                null,
                $account->toArray()
            );

            DB::commit();

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

    public function show($id)
    {
        $user = auth()->guard('finance')->user();
        $account = BankAccount::with(['financeGroup'])
            ->where('finance_group_id', $user->finance_group_id)
            ->findOrFail($id);

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

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

        $account = BankAccount::where('finance_group_id', $financeGroupId)->findOrFail($id);

        $request->validate([
            'finance_group_id' => 'required|exists:finance_groups,id',
            'bank_name' => 'required|string|max:255',
            'account_holder' => 'required|string|max:255',
            'iban' => 'required|string|max:34',
            'description' => 'nullable|string|max:255',
            'min_amount' => 'required|numeric|min:0',
            'max_amount' => 'required|numeric|gt:min_amount',
            'is_active' => 'boolean',
        ]);

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

        $hasDescriptionColumn = Schema::hasColumn('bank_accounts', 'description');
        if ($request->filled('description') && !$hasDescriptionColumn) {
            return response()->json([
                'success' => false,
                'message' => 'Aciklama alani kaydedilemiyor. Lutfen once veritabanini guncelleyin (description kolonu eksik).',
            ], 500);
        }

        DB::beginTransaction();
        try {
            $oldData = $account->toArray();

            $payload = [
                'finance_user_id' => $user->id,
                'finance_group_id' => $financeGroupId,
                'bank_name' => $request->bank_name,
                'account_holder_name' => $request->account_holder,
                'account_name' => $request->account_holder,
                'iban' => $request->iban,
                'min_amount' => $request->min_amount,
                'max_amount' => $request->max_amount,
            ];

            if (Schema::hasColumn('bank_accounts', 'is_blocked') && (bool) $account->is_blocked) {
                $payload['is_active'] = false;
            } elseif ($request->has('is_active')) {
                $payload['is_active'] = $request->boolean('is_active');
            }

            if ($hasDescriptionColumn) {
                $payload['description'] = $request->description;
            }

            if (Schema::hasColumn('bank_accounts', 'account_holder')) {
                $payload['account_holder'] = $request->account_holder;
            }

            $account->update($payload);

            ActivityLog::log(
                'update_bank_account',
                'bank_accounts',
                "Banka hesabı güncellendi: {$account->account_name}",
                $oldData,
                $account->toArray()
            );

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Banka hesabı başarıyla güncellendi.',
                'account' => $account,
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => 'Banka hesabı güncellenirken bir hata oluştu: ' . $e->getMessage(),
            ], 500);
        }
    }

    public function destroy($id)
    {
        $user = auth()->guard('finance')->user();
        $account = BankAccount::where('finance_group_id', $user->finance_group_id)->findOrFail($id);

        if ($account->transactions()->count() > 0) {
            return response()->json([
                'success' => false,
                'message' => 'Bu hesap ile ilişkili işlemler var. Hesap silinemez.',
            ], 400);
        }

        DB::beginTransaction();
        try {
            $accountName = $account->account_name;

            $account->delete();

            ActivityLog::log(
                'delete_bank_account',
                'bank_accounts',
                "Banka hesabı silindi: {$accountName}",
                $account->toArray(),
                null
            );

            DB::commit();

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

    public function toggleStatus($id)
    {
        $user = auth()->guard('finance')->user();
        $account = BankAccount::where('finance_group_id', $user->finance_group_id)->findOrFail($id);

        if (Schema::hasColumn('bank_accounts', 'is_blocked') && (bool) $account->is_blocked) {
            return response()->json([
                'success' => false,
                'message' => 'Bloke hesap aktif edilemez.',
            ], 422);
        }

        DB::beginTransaction();
        try {
            $oldStatus = $account->is_active;
            $account->update(['is_active' => !$oldStatus]);

            ActivityLog::log(
                'toggle_bank_account_status',
                'bank_accounts',
                "Banka hesabı durumu değiştirildi: {$account->account_name}",
                ['is_active' => $oldStatus],
                ['is_active' => $account->is_active]
            );

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => $account->is_active ? 'Hesap aktif edildi.' : 'Hesap pasif edildi.',
                'is_active' => $account->is_active,
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => 'Durum değiştirilirken bir hata oluştu: ' . $e->getMessage(),
            ], 500);
        }
    }

    public function block($id)
    {
        $user = auth()->guard('finance')->user();
        $account = BankAccount::where('finance_group_id', $user->finance_group_id)->findOrFail($id);

        if (!Schema::hasColumn('bank_accounts', 'is_blocked')) {
            return response()->json([
                'success' => false,
                'message' => 'Bloke ozelligi kullanima hazir degil. Lutfen veritabani migration calistirin.',
            ], 500);
        }

        DB::beginTransaction();
        try {
            $oldData = $account->only(['is_active', 'is_blocked']);

            $account->update([
                'is_blocked' => true,
                'is_active' => false,
            ]);

            BankAccountSiteStatus::where('bank_account_id', $account->id)->delete();

            ActivityLog::log(
                'block_bank_account',
                'bank_accounts',
                "Banka hesabi bloke edildi: {$account->account_name}",
                $oldData,
                $account->only(['is_active', 'is_blocked'])
            );

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Hesap bloke edildi ve pasife alindi.',
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => 'Hesap bloke edilirken bir hata olustu: ' . $e->getMessage(),
            ], 500);
        }
    }

    public function getByGroup($id)
    {
        $user = auth()->guard('finance')->user();
        $siteId = request()->filled('site_id') ? (int) request()->site_id : null;

        if ((int) $id !== (int) $user->finance_group_id) {
            return response()->json([
                'success' => false,
                'message' => 'Gecersiz finans grubu.',
            ], 403);
        }

        if ($siteId && !Site::whereKey($siteId)->exists()) {
            return response()->json([
                'success' => false,
                'message' => 'Gecersiz site.',
            ], 422);
        }

        $bankAccounts = BankAccount::query()
            ->where('finance_group_id', $user->finance_group_id)
            ->with('siteStatuses')
            ->when(Schema::hasColumn('bank_accounts', 'is_blocked'), function ($query) {
                $query->where('is_blocked', false);
            })
            ->when(!$siteId, function ($query) {
                $query->where('is_active', true);
            })
            ->get()
            ->filter(function (BankAccount $account) use ($siteId) {
                return !$siteId || $account->isActiveForSite($siteId);
            })
            ->values()
            ->map(function (BankAccount $account) {
                return [
                    'id' => $account->id,
                    'account_name' => $account->account_name,
                    'iban' => $account->iban,
                    'bank_name' => $account->bank_name,
                ];
            });

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

    public function siteStatuses($id)
    {
        $user = auth()->guard('finance')->user();
        $account = BankAccount::where('finance_group_id', $user->finance_group_id)->findOrFail($id);
        $isBlocked = Schema::hasColumn('bank_accounts', 'is_blocked') && (bool) $account->is_blocked;

        $sites = Site::orderBy('name')->get(['id', 'name', 'is_active']);
        $statusBySiteId = BankAccountSiteStatus::where('bank_account_id', $account->id)
            ->pluck('is_active', 'site_id');

        return response()->json([
            'success' => true,
            'account' => [
                'id' => $account->id,
                'bank_name' => $account->bank_name,
                'account_holder' => $account->account_holder,
                'iban' => $account->iban,
                'default_is_active' => $isBlocked ? false : (bool) $account->is_active,
                'is_blocked' => $isBlocked,
            ],
            'sites' => $sites->map(function (Site $site) use ($statusBySiteId) {
                $hasOverride = $statusBySiteId->has($site->id);
                $overrideStatus = 'default';
                if ($hasOverride) {
                    $overrideStatus = ((bool) $statusBySiteId->get($site->id)) ? 'active' : 'passive';
                }

                return [
                    'id' => $site->id,
                    'name' => $site->name,
                    'is_active' => (bool) $site->is_active,
                    'override_status' => $overrideStatus,
                ];
            })->values(),
        ]);
    }

    public function updateSiteStatuses(Request $request, $id)
    {
        $user = auth()->guard('finance')->user();
        $account = BankAccount::where('finance_group_id', $user->finance_group_id)->findOrFail($id);

        if (Schema::hasColumn('bank_accounts', 'is_blocked') && (bool) $account->is_blocked) {
            return response()->json([
                'success' => false,
                'message' => 'Bloke hesaplar icin site bazli durum degistirilemez.',
            ], 422);
        }

        $request->validate([
            'statuses' => 'nullable|array',
            'statuses.*' => 'nullable|in:default,active,passive',
        ]);

        $validSiteIds = Site::pluck('id')->map(function ($value) {
            return (int) $value;
        })->all();

        DB::beginTransaction();
        try {
            $oldStatuses = BankAccountSiteStatus::where('bank_account_id', $account->id)->get()->map(function ($status) {
                return [
                    'site_id' => (int) $status->site_id,
                    'is_active' => (bool) $status->is_active,
                ];
            })->values()->all();

            foreach ((array) $request->input('statuses', []) as $rawSiteId => $rawStatus) {
                $siteId = (int) $rawSiteId;
                if (!in_array($siteId, $validSiteIds, true)) {
                    continue;
                }

                $status = strtolower(trim((string) $rawStatus));
                if ($status === '' || $status === 'default') {
                    BankAccountSiteStatus::where('bank_account_id', $account->id)
                        ->where('site_id', $siteId)
                        ->delete();
                    continue;
                }

                $isActive = $status === 'active';
                BankAccountSiteStatus::updateOrCreate(
                    [
                        'bank_account_id' => $account->id,
                        'site_id' => $siteId,
                    ],
                    [
                        'is_active' => $isActive,
                    ]
                );
            }

            $newStatuses = BankAccountSiteStatus::where('bank_account_id', $account->id)->get()->map(function ($status) {
                return [
                    'site_id' => (int) $status->site_id,
                    'is_active' => (bool) $status->is_active,
                ];
            })->values()->all();

            ActivityLog::log(
                'update_bank_account_site_statuses',
                'bank_accounts',
                "Banka hesabi site durumlari guncellendi: {$account->account_name}",
                ['site_statuses' => $oldStatuses],
                ['site_statuses' => $newStatuses]
            );

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Site bazli durumlar guncellendi.',
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => 'Site durumlari guncellenirken bir hata olustu: ' . $e->getMessage(),
            ], 500);
        }
    }
}


