<?php
declare(strict_types=1);

namespace App\Core;

final class Response
{
    private string $body = '';
    private int $statusCode = 200;
    private array $headers = [];
    private ?string $redirectUrl = null;
    private array $flashData = [];

    public function __construct(?string $redirectUrl = null)
    {
        if ($redirectUrl !== null) {
            $this->redirectUrl = $redirectUrl;
            $this->statusCode = 302;
        }
    }

    public function html(string $content, int $status = 200): self
    {
        $this->body = $content;
        $this->statusCode = $status;
        $this->headers['Content-Type'] = 'text/html; charset=UTF-8';
        return $this;
    }

    public function json($data, int $status = 200): self
    {
        $this->body = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        $this->statusCode = $status;
        $this->headers['Content-Type'] = 'application/json; charset=UTF-8';
        return $this;
    }

    public function redirect(string $url, int $status = 302): self
    {
        $this->redirectUrl = $url;
        $this->statusCode = $status;
        return $this;
    }

    public function withSuccess(string $message): self
    {
        $session = App::getInstance()->session();
        $alerts = $session->get('_flash._alerts', []);
        if (!is_array($alerts)) $alerts = [];
        $alerts[] = ['type' => 'success', 'message' => $message];
        $session->flash('_alerts', $alerts);
        return $this;
    }

    public function withError(string $message): self
    {
        $session = App::getInstance()->session();
        $alerts = $session->get('_flash._alerts', []);
        if (!is_array($alerts)) $alerts = [];
        $alerts[] = ['type' => 'error', 'message' => $message];
        $session->flash('_alerts', $alerts);
        return $this;
    }

    public function withInput(array $data): self
    {
        App::getInstance()->session()->flash('_old_input', $data);
        return $this;
    }

    public function withWarning(string $message): self
    {
        $session = App::getInstance()->session();
        $alerts = $session->get('_flash._alerts', []);
        if (!is_array($alerts)) $alerts = [];
        $alerts[] = ['type' => 'warning', 'message' => $message];
        $session->flash('_alerts', $alerts);
        return $this;
    }

    public function status(int $code): self
    {
        $this->statusCode = $code;
        return $this;
    }

    public function header(string $key, string $value): self
    {
        $this->headers[$key] = $value;
        return $this;
    }

    public function withHeaders(array $headers): self
    {
        foreach ($headers as $key => $value) {
            $this->headers[$key] = $value;
        }
        return $this;
    }

    public function download(string $filePath, string $filename): self
    {
        if (!file_exists($filePath)) {
            $this->statusCode = 404;
            $this->body = 'File not found';
            return $this;
        }

        $this->headers['Content-Type'] = mime_content_type($filePath) ?: 'application/octet-stream';
        $this->headers['Content-Disposition'] = 'attachment; filename="' . $filename . '"';
        $this->headers['Content-Length'] = (string) filesize($filePath);
        $this->body = file_get_contents($filePath);
        return $this;
    }

    public function send(): void
    {
        // Handle redirect
        if ($this->redirectUrl !== null) {
            http_response_code($this->statusCode);
            header('Location: ' . $this->redirectUrl);
            exit;
        }

        // Set status code
        http_response_code($this->statusCode);

        // Set headers
        foreach ($this->headers as $key => $value) {
            header("{$key}: {$value}");
        }

        // Output body
        echo $this->body;
        exit;
    }
}