<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Client;
use App\Models\PlatformConnection;
use App\Services\Credentials\CredentialVault;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

abstract class BaseAccountController extends Controller
{
    abstract protected function platform(): string;

    abstract protected function title(): string;

    public function __construct(protected CredentialVault $vault) {}

    public function index(): View
    {
        $page_title = $this->title();
        $page_description = 'API bağlantıları, token durumu ve test sonuçları';
        $platform = $this->platform();
        $connections = PlatformConnection::with(['client', 'secureCredential'])
            ->where('platform', $platform)
            ->latest()
            ->paginate(20);

        return view('admin.accounts.index', compact('page_title', 'page_description', 'platform', 'connections'));
    }

    public function create(): View
    {
        $page_title = $this->title().' Bağlantısı Ekle';
        $page_description = 'Faz 2: bilgiler güvenli token kasasına şifreli kaydedilir, bağlantı testi yapılabilir.';
        $platform = $this->platform();
        $connection = new PlatformConnection(['platform' => $platform, 'status' => 'draft']);
        $clients = Client::orderBy('company_name')->get();
        $credentialPayload = [];
        $maskedPayload = [];

        return view('admin.accounts.create', compact('page_title', 'page_description', 'platform', 'connection', 'clients', 'credentialPayload', 'maskedPayload'));
    }

    public function store(Request $request): RedirectResponse
    {
        $data = $this->validated($request);
        $data['platform'] = $this->platform();
        $meta = $this->extractMeta($request);
        if (! empty($meta)) {
            $data['meta'] = $meta;
        }

        $connection = PlatformConnection::create($data);
        $this->saveCredentialPayload($connection, $request);

        return redirect()->route('admin.accounts.'.$this->routeKey().'.show', $connection)->with('success', 'Bağlantı oluşturuldu. Şimdi bağlantı testi yapabilirsin.');
    }

    public function show(PlatformConnection $connection): View
    {
        abort_unless($connection->platform === $this->platform(), 404);

        $page_title = $connection->connection_name;
        $page_description = $this->title().' bağlantı detayı';
        $platform = $this->platform();
        $connection->load(['client', 'secureCredential']);
        $maskedPayload = $this->vault->maskedPayload($connection->secureCredential);
        $credentialPayload = [];

        return view('admin.accounts.show', compact('page_title', 'page_description', 'platform', 'connection', 'maskedPayload', 'credentialPayload'));
    }

    public function edit(PlatformConnection $connection): View
    {
        abort_unless($connection->platform === $this->platform(), 404);

        $page_title = $this->title().' Bağlantısı Düzenle';
        $page_description = $connection->connection_name;
        $platform = $this->platform();
        $clients = Client::orderBy('company_name')->get();
        $connection->load('secureCredential');
        $credentialPayload = [];
        $maskedPayload = $this->vault->maskedPayload($connection->secureCredential);

        return view('admin.accounts.edit', compact('page_title', 'page_description', 'platform', 'connection', 'clients', 'credentialPayload', 'maskedPayload'));
    }

    public function update(Request $request, PlatformConnection $connection): RedirectResponse
    {
        abort_unless($connection->platform === $this->platform(), 404);

        $data = $this->validated($request);
        $meta = array_merge($connection->meta ?? [], $this->extractMeta($request));
        if (! empty($meta)) {
            $data['meta'] = $meta;
        }

        $connection->update($data);
        $this->saveCredentialPayload($connection->refresh(), $request);

        return redirect()->route('admin.accounts.'.$this->routeKey().'.show', $connection)->with('success', 'Bağlantı güncellendi.');
    }

    public function destroy(PlatformConnection $connection): RedirectResponse
    {
        abort_unless($connection->platform === $this->platform(), 404);
        $connection->delete();

        return redirect()->route('admin.accounts.'.$this->routeKey().'.index')->with('success', 'Bağlantı silindi. Token kaydı sistemde pasif bırakılmadıysa ayrıca token kasasından yönetilebilir.');
    }

    protected function routeKey(): string
    {
        return match ($this->platform()) {
            'google_ads' => 'google-ads',
            'meta_ads' => 'meta-ads',
            'search_console' => 'search-console',
            'ga4' => 'ga4',
            default => $this->platform(),
        };
    }

    private function validated(Request $request): array
    {
        return $request->validate([
            'client_id' => ['required', 'exists:clients,id'],
            'connection_name' => ['required', 'string', 'max:255'],
            'account_id' => ['nullable', 'string', 'max:255'],
            'account_name' => ['nullable', 'string', 'max:255'],
            'status' => ['required', 'in:draft,active,error,paused'],
            'currency_code' => ['nullable', 'string', 'size:3'],
            'timezone' => ['nullable', 'string', 'max:80'],
            'last_error' => ['nullable', 'string'],
        ]);
    }

    private function saveCredentialPayload(PlatformConnection $connection, Request $request): void
    {
        [$sensitive, $nonSensitive] = $this->credentialKeys();
        $incoming = $request->only(array_merge($sensitive, $nonSensitive));

        $this->vault->upsertForConnection($connection->load('secureCredential'), $incoming, $sensitive, $nonSensitive);
    }

    private function credentialKeys(): array
    {
        return match ($this->platform()) {
            'google_ads' => [
                ['google_client_secret', 'refresh_token', 'developer_token'],
                ['google_client_id', 'login_customer_id', 'customer_id'],
            ],
            'meta_ads' => [
                ['app_secret', 'access_token'],
                ['app_id', 'business_id', 'ad_account_id'],
            ],
            'search_console' => [
                ['google_client_secret', 'refresh_token'],
                ['google_client_id', 'site_url'],
            ],
            'ga4' => [
                ['google_client_secret', 'refresh_token'],
                ['google_client_id', 'property_id'],
            ],
            default => [[], []],
        };
    }

    private function extractMeta(Request $request): array
    {
        $keys = match ($this->platform()) {
            'google_ads' => ['login_customer_id', 'customer_id'],
            'meta_ads' => ['business_id', 'ad_account_id'],
            'search_console' => ['site_url'],
            'ga4' => ['property_id'],
            default => [],
        };

        return collect($request->only($keys))
            ->filter(fn ($value) => filled($value))
            ->all();
    }
}
