<?php

declare(strict_types=1);

namespace App\Controllers\Admin;

use App\Controllers\BaseController;
use App\Models\FeedbackFileModel;
use App\Models\FeedbackModel;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Roles;

/**
 * 사용자 의견 검토(관리자). super·본부는 전체, 지자체관리자는 자기 지자체만.
 */
class Feedback extends BaseController
{
    private function scopeLgIdx(): ?int
    {
        helper('admin');
        $level = (int) session()->get('mb_level');
        if (Roles::isSuperAdminEquivalent($level)) {
            return null; // 전체
        }

        return admin_effective_lg_idx();
    }

    public function index(): string
    {
        $model = model(FeedbackModel::class);
        $builder = $model->orderBy('fb_idx', 'DESC');

        $scope = $this->scopeLgIdx();
        if ($scope !== null) {
            $builder->where('fb_lg_idx', $scope);
        }

        $status = (string) ($this->request->getGet('status') ?? '');
        if (in_array($status, FeedbackModel::STATUSES, true)) {
            $builder->where('fb_status', $status);
        }

        $list  = $builder->paginate(20);
        $pager = $model->pager;

        return view('admin/layout', [
            'title'   => '사용자 의견',
            'content' => view('admin/feedback/index', [
                'list'   => $list,
                'pager'  => $pager,
                'status' => $status,
            ]),
        ]);
    }

    /**
     * 전체 의견을 한 페이지에서 스크롤로 훑어볼 수 있는 화면(상세 클릭 없이 내용 전체 표시).
     */
    public function all(): string
    {
        $model = model(FeedbackModel::class);
        $builder = $model->orderBy('fb_idx', 'DESC');

        $scope = $this->scopeLgIdx();
        if ($scope !== null) {
            $builder->where('fb_lg_idx', $scope);
        }

        $status = (string) ($this->request->getGet('status') ?? '');
        if (in_array($status, FeedbackModel::STATUSES, true)) {
            $builder->where('fb_status', $status);
        }

        $list = $builder->findAll();

        $ids = array_map(static fn ($r): int => (int) $r->fb_idx, $list);
        $filesByFb = [];
        if ($ids !== []) {
            $files = model(FeedbackFileModel::class)
                ->whereIn('ff_fb_idx', $ids)
                ->orderBy('ff_idx', 'ASC')
                ->findAll();
            foreach ($files as $f) {
                $filesByFb[(int) $f->ff_fb_idx][] = $f;
            }
        }

        return view('admin/layout', [
            'title'   => '사용자 의견 · 전체보기',
            'content' => view('admin/feedback/all', [
                'list'      => $list,
                'filesByFb' => $filesByFb,
                'status'    => $status,
            ]),
        ]);
    }

    public function show(int $id): string|ResponseInterface
    {
        $model = model(FeedbackModel::class);
        $row   = $model->find($id);
        $scope = $this->scopeLgIdx();
        if ($row === null || ($scope !== null && (int) $row->fb_lg_idx !== $scope)) {
            return redirect()->to(site_url('admin/feedback'))->with('error', '의견을 찾을 수 없습니다.');
        }

        $files = model(FeedbackFileModel::class)
            ->where('ff_fb_idx', $id)
            ->orderBy('ff_idx', 'ASC')
            ->findAll();

        return view('admin/layout', [
            'title'   => '의견 상세',
            'content' => view('admin/feedback/show', ['row' => $row, 'files' => $files]),
        ]);
    }

    public function updateStatus(int $id): ResponseInterface
    {
        $model = model(FeedbackModel::class);
        $row   = $model->find($id);
        $scope = $this->scopeLgIdx();
        if ($row === null || ($scope !== null && (int) $row->fb_lg_idx !== $scope)) {
            return redirect()->to(site_url('admin/feedback'))->with('error', '의견을 찾을 수 없습니다.');
        }

        $status = (string) $this->request->getPost('fb_status');
        $memo   = (string) $this->request->getPost('fb_admin_memo');
        $update = ['fb_admin_memo' => mb_substr($memo, 0, 2000)];
        if (in_array($status, FeedbackModel::STATUSES, true)) {
            $update['fb_status'] = $status;
        }
        $model->update($id, $update);

        // 전체보기 화면에서 저장한 경우 스크롤 위치(#fb-{id})를 유지한 채 그 화면으로 되돌아간다.
        $returnTo = (string) $this->request->getPost('return_to');
        if ($returnTo === 'all') {
            return redirect()->to(site_url('admin/feedback/all') . '#fb-' . $id)->with('success', '처리 상태를 저장했습니다.');
        }

        return redirect()->to(site_url('admin/feedback/' . $id))->with('success', '처리 상태를 저장했습니다.');
    }

    /** 스크린샷 이미지 서빙 (관리자만, writable 보호 유지) */
    public function image(int $id): ResponseInterface
    {
        $model = model(FeedbackModel::class);
        $row   = $model->find($id);
        $scope = $this->scopeLgIdx();
        if ($row === null || ($scope !== null && (int) $row->fb_lg_idx !== $scope) || empty($row->fb_screenshot)) {
            return $this->response->setStatusCode(404)->setBody('not found');
        }

        $path = WRITEPATH . 'uploads/feedback/' . basename((string) $row->fb_screenshot);
        if (! is_file($path)) {
            return $this->response->setStatusCode(404)->setBody('not found');
        }

        $mime = str_ends_with($path, '.png') ? 'image/png' : 'image/jpeg';

        return $this->response
            ->setHeader('Content-Type', $mime)
            ->setHeader('Cache-Control', 'private, max-age=300')
            ->setBody((string) file_get_contents($path));
    }

    /** 첨부 이미지(feedback_file) 서빙 — 관리자만, 테넌트 검증 */
    public function file(int $ffIdx): ResponseInterface
    {
        $ff = model(FeedbackFileModel::class)->find($ffIdx);
        if ($ff === null) {
            return $this->response->setStatusCode(404)->setBody('not found');
        }
        $fb    = model(FeedbackModel::class)->find((int) $ff->ff_fb_idx);
        $scope = $this->scopeLgIdx();
        if ($fb === null || ($scope !== null && (int) $fb->fb_lg_idx !== $scope)) {
            return $this->response->setStatusCode(404)->setBody('not found');
        }

        $path = WRITEPATH . 'uploads/feedback/' . basename((string) $ff->ff_path);
        if (! is_file($path)) {
            return $this->response->setStatusCode(404)->setBody('not found');
        }

        $mime = (string) ($ff->ff_mime ?: (str_ends_with($path, '.png') ? 'image/png' : 'image/jpeg'));

        return $this->response
            ->setHeader('Content-Type', $mime)
            ->setHeader('Cache-Control', 'private, max-age=300')
            ->setBody((string) file_get_contents($path));
    }
}
