<?php

declare(strict_types=1);

namespace App\Controllers;

use CodeIgniter\Database\Exceptions\DatabaseException;
use App\Models\BagInventoryModel;
use App\Models\BagIssueModel;
use App\Models\BagOrderModel;
use App\Models\BagOrderItemModel;
use App\Models\BagPriceModel;
use App\Models\BagReceivingModel;
use App\Models\BagSaleModel;
use App\Models\CodeKindModel;
use App\Models\CodeDetailModel;
use App\Models\CompanyModel;
use App\Models\PackagingUnitModel;
use App\Models\SalesAgencyModel;
use App\Models\ShopOrderModel;
use App\Models\DesignatedShopModel;
use Config\Roles;

class Bag extends BaseController
{
    /**
     * 로그인 사용자의 지자체 PK 반환 (미로그인/미지정 시 null)
     */
    private function lgIdx(): ?int
    {
        helper('admin');
        return admin_effective_lg_idx();
    }

    private function render(string $title, string $viewFile, array $data = []): string
    {
        return view('bag/layout/main', [
            'title'   => $title,
            'content' => view($viewFile, $data),
        ]);
    }

    // ──────────────────────────────────────────────
    // 기본정보관리
    // ──────────────────────────────────────────────
    public function basicInfo(): string
    {
        $lgIdx = $this->lgIdx();
        $data = [
            'bagPrices'      => [],
            'packagingUnits' => [],
        ];

        if ($lgIdx) {
            try {
                $data['bagPrices'] = model(BagPriceModel::class)->where('bp_lg_idx', $lgIdx)->orderBy('bp_bag_code', 'ASC')->findAll();
            } catch (DatabaseException $e) {
                log_message('error', '[basicInfo] bag_price 조회 실패(테이블 미생성 등): ' . $e->getMessage());
            }
            try {
                $data['packagingUnits'] = model(PackagingUnitModel::class)->where('pu_lg_idx', $lgIdx)->orderBy('pu_bag_code', 'ASC')->findAll();
            } catch (DatabaseException $e) {
                log_message('error', '[basicInfo] packaging_unit 조회 실패: ' . $e->getMessage());
            }
        }

        return $this->render('기본정보관리', 'bag/basic_info', $data);
    }

    /**
     * 기본코드 종류·세부코드 조회 전용 (사이트 메뉴 기본코드관리)
     */
    public function codeKinds(): string
    {
        $kindModel   = model(CodeKindModel::class);
        $detailModel = model(CodeDetailModel::class);
        $kinds       = $kindModel->orderBy('ck_code', 'ASC')->findAll();
        $countMap    = [];
        foreach ($kinds as $row) {
            // countAllResults() 기본값(true)으로 매번 빌더 초기화 — false 시 where 누적되어 2번째부터 0건으로 보임
            $countMap[$row->ck_idx] = (int) $detailModel->where('cd_ck_idx', $row->ck_idx)->countAllResults();
        }

        return $this->render('기본코드관리', 'bag/code_kinds', [
            'codeKinds' => $kinds,
            'countMap'  => $countMap,
            'canManage' => Roles::canManageCodeMaster((int) session()->get('mb_level')),
        ]);
    }

    /**
     * 기본코드 세부 목록 (사이트 레이아웃). 등록·수정·삭제 폼은 /admin/code-details/* 유지.
     */
    public function codeDetails(int $ckIdx)
    {
        $kindModel   = model(CodeKindModel::class);
        $detailModel = model(CodeDetailModel::class);
        $kind        = $kindModel->find($ckIdx);
        if ($kind === null) {
            return redirect()->to(site_url('bag/code-kinds'))->with('error', '코드 종류를 찾을 수 없습니다.');
        }

        $list = $detailModel->where('cd_ck_idx', $ckIdx)->orderBy('cd_sort', 'ASC')->orderBy('cd_idx', 'ASC')->paginate(20);
        $pager = $detailModel->pager;

        $canManage = Roles::canManageCodeMaster((int) session()->get('mb_level'));
        $title     = ($canManage ? '세부코드 관리' : '세부코드 조회') . ' — ' . $kind->ck_name . ' (' . $kind->ck_code . ')';

        return $this->render($title, 'bag/code_details', [
            'kind'      => $kind,
            'list'      => $list,
            'pager'     => $pager,
            'canManage' => $canManage,
        ]);
    }

    // ──────────────────────────────────────────────
    // 발주 입고 관리
    // ──────────────────────────────────────────────
    public function purchaseInbound(): string
    {
        $lgIdx = $this->lgIdx();
        $data = ['orders' => [], 'receivings' => [], 'startDate' => null, 'endDate' => null];

        if ($lgIdx) {
            $startDate = $this->request->getGet('start_date');
            $endDate   = $this->request->getGet('end_date');
            $data['startDate'] = $startDate;
            $data['endDate']   = $endDate;

            // 발주 목록
            $orderBuilder = model(BagOrderModel::class)->where('bo_lg_idx', $lgIdx);
            if ($startDate) $orderBuilder->where('bo_order_date >=', $startDate);
            if ($endDate)   $orderBuilder->where('bo_order_date <=', $endDate);
            $data['orders'] = $orderBuilder->orderBy('bo_order_date', 'DESC')->paginate(20, 'orders');
            $data['orderPager'] = model(BagOrderModel::class)->pager;

            // 발주별 품목 합계
            $itemSummary = [];
            foreach ($data['orders'] as $order) {
                $items = model(BagOrderItemModel::class)->where('boi_bo_idx', $order->bo_idx)->findAll();
                $totalQty = 0;
                $totalAmt = 0;
                foreach ($items as $it) {
                    $totalQty += (int) $it->boi_qty_sheet;
                    $totalAmt += (float) $it->boi_amount;
                }
                $itemSummary[$order->bo_idx] = ['qty' => $totalQty, 'amount' => $totalAmt, 'count' => count($items)];
            }
            $data['itemSummary'] = $itemSummary;

            // 입고 목록
            $recvBuilder = model(BagReceivingModel::class)->where('br_lg_idx', $lgIdx);
            if ($startDate) $recvBuilder->where('br_receive_date >=', $startDate);
            if ($endDate)   $recvBuilder->where('br_receive_date <=', $endDate);
            $data['receivings'] = $recvBuilder->orderBy('br_receive_date', 'DESC')->paginate(20, 'receivings');
            $data['recvPager'] = model(BagReceivingModel::class)->pager;
        }

        return $this->render('발주 입고 관리', 'bag/purchase_inbound', $data);
    }

    // ──────────────────────────────────────────────
    // 불출 관리
    // ──────────────────────────────────────────────
    public function issue(): string
    {
        $lgIdx = $this->lgIdx();
        $data = ['list' => [], 'startDate' => null, 'endDate' => null];

        if ($lgIdx) {
            $startDate = $this->request->getGet('start_date');
            $endDate   = $this->request->getGet('end_date');
            $data['startDate'] = $startDate;
            $data['endDate']   = $endDate;

            $builder = model(BagIssueModel::class)->where('bi2_lg_idx', $lgIdx);
            if ($startDate) $builder->where('bi2_issue_date >=', $startDate);
            if ($endDate)   $builder->where('bi2_issue_date <=', $endDate);
            $data['list'] = $builder->orderBy('bi2_issue_date', 'DESC')->paginate(20);
            $data['pager'] = model(BagIssueModel::class)->pager;
        }

        return $this->render('불출 관리', 'bag/issue', $data);
    }

    // ──────────────────────────────────────────────
    // 재고 관리
    // ──────────────────────────────────────────────
    public function inventory(): string
    {
        $lgIdx = $this->lgIdx();
        $data = ['list' => []];

        if ($lgIdx) {
            $invModel = model(BagInventoryModel::class);
            $data['list'] = $invModel->where('bi_lg_idx', $lgIdx)->orderBy('bi_bag_code', 'ASC')->paginate(20);
            $data['pager'] = $invModel->pager;
        }

        return $this->render('재고 관리', 'bag/inventory', $data);
    }

    // ──────────────────────────────────────────────
    // 판매 관리
    // ──────────────────────────────────────────────
    public function sales(): string
    {
        $lgIdx = $this->lgIdx();
        $data = ['salesList' => [], 'orderList' => [], 'startDate' => null, 'endDate' => null];

        if ($lgIdx) {
            $startDate = $this->request->getGet('start_date');
            $endDate   = $this->request->getGet('end_date');
            $data['startDate'] = $startDate;
            $data['endDate']   = $endDate;

            // 판매/반품
            $saleBuilder = model(BagSaleModel::class)->where('bs_lg_idx', $lgIdx);
            if ($startDate) $saleBuilder->where('bs_sale_date >=', $startDate);
            if ($endDate)   $saleBuilder->where('bs_sale_date <=', $endDate);
            $data['salesList'] = $saleBuilder->orderBy('bs_sale_date', 'DESC')->paginate(20, 'sales');
            $data['salesPager'] = model(BagSaleModel::class)->pager;

            // 주문 접수
            $orderBuilder = model(ShopOrderModel::class)->where('so_lg_idx', $lgIdx);
            if ($startDate) $orderBuilder->where('so_delivery_date >=', $startDate);
            if ($endDate)   $orderBuilder->where('so_delivery_date <=', $endDate);
            $data['orderList'] = $orderBuilder->orderBy('so_idx', 'DESC')->paginate(20, 'shoporders');
            $data['orderPager'] = model(ShopOrderModel::class)->pager;
        }

        return $this->render('판매 관리', 'bag/sales', $data);
    }

    // ──────────────────────────────────────────────
    // 판매 현황
    // ──────────────────────────────────────────────
    public function salesStats(): string
    {
        $lgIdx = $this->lgIdx();
        $data = ['result' => [], 'startDate' => null, 'endDate' => null];

        if ($lgIdx) {
            $startDate = $this->request->getGet('start_date');
            $endDate   = $this->request->getGet('end_date');
            $data['startDate'] = $startDate;
            $data['endDate']   = $endDate;

            $builder = model(BagSaleModel::class)->where('bs_lg_idx', $lgIdx)->where('bs_type', 'sale');
            if ($startDate) $builder->where('bs_sale_date >=', $startDate);
            if ($endDate)   $builder->where('bs_sale_date <=', $endDate);
            $data['result'] = $builder->orderBy('bs_sale_date', 'DESC')->paginate(20);
            $data['pager'] = model(BagSaleModel::class)->pager;
        }

        return $this->render('판매 현황', 'bag/sales_stats', $data);
    }

    // ──────────────────────────────────────────────
    // 봉투 수불 관리
    // ──────────────────────────────────────────────
    public function flow(): string
    {
        $lgIdx = $this->lgIdx();
        $data = ['receiving' => [], 'sales' => [], 'issues' => [], 'inventory' => [], 'startDate' => null, 'endDate' => null];

        if ($lgIdx) {
            $startDate = $this->request->getGet('start_date');
            $endDate   = $this->request->getGet('end_date');
            $data['startDate'] = $startDate;
            $data['endDate']   = $endDate;

            $data['inventory'] = model(BagInventoryModel::class)->where('bi_lg_idx', $lgIdx)->findAll();

            $recvBuilder = model(BagReceivingModel::class)->where('br_lg_idx', $lgIdx);
            if ($startDate) $recvBuilder->where('br_receive_date >=', $startDate);
            if ($endDate)   $recvBuilder->where('br_receive_date <=', $endDate);
            $data['receiving'] = $recvBuilder->findAll();

            $saleBuilder = model(BagSaleModel::class)->where('bs_lg_idx', $lgIdx);
            if ($startDate) $saleBuilder->where('bs_sale_date >=', $startDate);
            if ($endDate)   $saleBuilder->where('bs_sale_date <=', $endDate);
            $data['sales'] = $saleBuilder->findAll();

            $issueBuilder = model(BagIssueModel::class)->where('bi2_lg_idx', $lgIdx);
            if ($startDate) $issueBuilder->where('bi2_issue_date >=', $startDate);
            if ($endDate)   $issueBuilder->where('bi2_issue_date <=', $endDate);
            $data['issues'] = $issueBuilder->findAll();
        }

        return $this->render('봉투 수불 관리', 'bag/flow', $data);
    }

    // ──────────────────────────────────────────────
    // 통계 분석 관리
    // ──────────────────────────────────────────────
    public function analytics(): string
    {
        return $this->render('통계 분석 관리', 'bag/analytics', []);
    }

    // ──────────────────────────────────────────────
    // 창 (프로그램 창 관리 - 추후)
    // ──────────────────────────────────────────────
    public function window(): string
    {
        return $this->render('창', 'bag/window', []);
    }

    // ──────────────────────────────────────────────
    // 도움말
    // ──────────────────────────────────────────────
    public function help(): string
    {
        return $this->render('도움말', 'bag/help', []);
    }

    // ──────────────────────────────────────────────
    // 재고 조정 (실사)
    // ──────────────────────────────────────────────
    public function inventoryAdjust(): string
    {
        $lgIdx = $this->lgIdx();
        $inventory = $lgIdx ? model(BagInventoryModel::class)->where('bi_lg_idx', $lgIdx)->orderBy('bi_bag_code')->findAll() : [];
        return $this->render('재고 조정', 'bag/inventory_adjust', compact('inventory'));
    }

    public function inventoryAdjustStore()
    {
        helper('admin');
        $lgIdx = $this->lgIdx();
        if (! $lgIdx) {
            return redirect()->to(site_url('bag/inventory'))->with('error', '지자체를 선택해 주세요.');
        }

        $rules = [
            'bag_code'    => 'required|max_length[50]',
            'adjust_type' => 'required|in_list[set,add,sub]',
            'qty'         => 'required|is_natural',
        ];
        if (! $this->validate($rules)) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $bagCode = $this->request->getPost('bag_code');
        $type    = $this->request->getPost('adjust_type');
        $qty     = (int) $this->request->getPost('qty');

        $invModel = model(BagInventoryModel::class);
        $existing = $invModel->where('bi_lg_idx', $lgIdx)->where('bi_bag_code', $bagCode)->first();

        if ($type === 'set') {
            if ($existing) {
                $invModel->update($existing->bi_idx, ['bi_qty' => $qty, 'bi_updated_at' => date('Y-m-d H:i:s')]);
            }
        } elseif ($type === 'add') {
            $bagName = $existing ? $existing->bi_bag_name : '';
            $invModel->adjustQty($lgIdx, $bagCode, $bagName, $qty);
        } elseif ($type === 'sub') {
            $bagName = $existing ? $existing->bi_bag_name : '';
            $invModel->adjustQty($lgIdx, $bagCode, $bagName, -$qty);
        }

        return redirect()->to(site_url('bag/inventory'))->with('success', '재고가 조정되었습니다.');
    }

    // ══════════════════════════════════════════════
    //  CRUD — 사이트 레이아웃으로 등록/처리 폼 제공
    // ══════════════════════════════════════════════

    // --- 불출 등록 ---
    public function issueCreate(): string
    {
        $kind = model(CodeKindModel::class)->where('ck_code', 'O')->first();
        $bagCodes = $kind ? model(CodeDetailModel::class)->where('cd_ck_idx', $kind->ck_idx)->where('cd_state', 1)->orderBy('cd_sort')->findAll() : [];
        return $this->render('불출 처리', 'bag/create_bag_issue', compact('bagCodes'));
    }

    public function issueStore()
    {
        $admin = new \App\Controllers\Admin\BagIssue();
        $admin->initController($this->request, $this->response, service('logger'));
        $result = $admin->store();
        if ($result instanceof \CodeIgniter\HTTP\RedirectResponse) {
            $to = (string) $result->getHeaderLine('Location');
            $to = str_replace('/admin/bag-issues', '/bag/issue', $to);
            return redirect()->to($to)->with('success', session()->getFlashdata('success'))->with('errors', session()->getFlashdata('errors'));
        }
        return redirect()->to(site_url('bag/issue'))->with('success', '불출 처리되었습니다.');
    }

    public function issueCancel(int $id)
    {
        $admin = new \App\Controllers\Admin\BagIssue();
        $admin->initController($this->request, $this->response, service('logger'));
        $admin->cancel($id);
        return redirect()->to(site_url('bag/issue'))->with('success', session()->getFlashdata('success') ?? '취소되었습니다.');
    }

    // --- 발주 등록 ---
    public function orderCreate(): string
    {
        helper('admin');
        $lgIdx = $this->lgIdx();
        $companies = $lgIdx ? model(CompanyModel::class)->where('cp_lg_idx', $lgIdx)->where('cp_type', 'manufacturer')->where('cp_state', 1)->findAll() : [];
        $agencies = $lgIdx ? model(SalesAgencyModel::class)->where('sa_lg_idx', $lgIdx)->where('sa_state', 1)->findAll() : [];
        $kind = model(CodeKindModel::class)->where('ck_code', 'O')->first();
        $bagCodes = $kind ? model(CodeDetailModel::class)->where('cd_ck_idx', $kind->ck_idx)->where('cd_state', 1)->orderBy('cd_sort')->findAll() : [];
        return $this->render('발주 등록', 'bag/create_bag_order', compact('companies', 'agencies', 'bagCodes'));
    }

    public function orderStore()
    {
        $admin = new \App\Controllers\Admin\BagOrder();
        $admin->initController($this->request, $this->response, service('logger'));
        $result = $admin->store();
        if ($result instanceof \CodeIgniter\HTTP\RedirectResponse) {
            return redirect()->to(site_url('bag/purchase-inbound'))->with('success', session()->getFlashdata('success'))->with('errors', session()->getFlashdata('errors'));
        }
        return redirect()->to(site_url('bag/purchase-inbound'))->with('success', '발주 등록되었습니다.');
    }

    // --- 입고 처리 ---
    public function receivingCreate(): string
    {
        helper('admin');
        $lgIdx = $this->lgIdx();
        $orders = $lgIdx ? model(BagOrderModel::class)->where('bo_lg_idx', $lgIdx)->where('bo_status', 'normal')->orderBy('bo_order_date', 'DESC')->findAll() : [];
        return $this->render('입고 처리', 'bag/create_bag_receiving', compact('orders'));
    }

    public function receivingStore()
    {
        $admin = new \App\Controllers\Admin\BagReceiving();
        $admin->initController($this->request, $this->response, service('logger'));
        $result = $admin->store();
        if ($result instanceof \CodeIgniter\HTTP\RedirectResponse) {
            return redirect()->to(site_url('bag/purchase-inbound'))->with('success', session()->getFlashdata('success'))->with('errors', session()->getFlashdata('errors'));
        }
        return redirect()->to(site_url('bag/purchase-inbound'))->with('success', '입고 처리되었습니다.');
    }

    // --- 판매 등록 ---
    public function saleCreate(): string
    {
        helper('admin');
        $lgIdx = $this->lgIdx();
        $shops = $lgIdx ? model(DesignatedShopModel::class)->where('ds_lg_idx', $lgIdx)->where('ds_state', 1)->findAll() : [];
        $kind = model(CodeKindModel::class)->where('ck_code', 'O')->first();
        $bagCodes = $kind ? model(CodeDetailModel::class)->where('cd_ck_idx', $kind->ck_idx)->where('cd_state', 1)->orderBy('cd_sort')->findAll() : [];
        return $this->render('판매 등록', 'bag/create_bag_sale', compact('shops', 'bagCodes'));
    }

    public function saleStore()
    {
        $admin = new \App\Controllers\Admin\BagSale();
        $admin->initController($this->request, $this->response, service('logger'));
        $result = $admin->store();
        if ($result instanceof \CodeIgniter\HTTP\RedirectResponse) {
            return redirect()->to(site_url('bag/sales'))->with('success', session()->getFlashdata('success'))->with('errors', session()->getFlashdata('errors'));
        }
        return redirect()->to(site_url('bag/sales'))->with('success', '판매 등록되었습니다.');
    }

    // --- 주문 접수 ---
    public function shopOrderCreate(): string
    {
        helper('admin');
        $lgIdx = $this->lgIdx();
        $shops = $lgIdx ? model(DesignatedShopModel::class)->where('ds_lg_idx', $lgIdx)->where('ds_state', 1)->findAll() : [];
        $kind = model(CodeKindModel::class)->where('ck_code', 'O')->first();
        $bagCodes = $kind ? model(CodeDetailModel::class)->where('cd_ck_idx', $kind->ck_idx)->where('cd_state', 1)->orderBy('cd_sort')->findAll() : [];
        return $this->render('주문 접수', 'bag/create_shop_order', compact('shops', 'bagCodes'));
    }

    public function shopOrderStore()
    {
        $admin = new \App\Controllers\Admin\ShopOrder();
        $admin->initController($this->request, $this->response, service('logger'));
        $result = $admin->store();
        if ($result instanceof \CodeIgniter\HTTP\RedirectResponse) {
            return redirect()->to(site_url('bag/sales'))->with('success', session()->getFlashdata('success'))->with('errors', session()->getFlashdata('errors'));
        }
        return redirect()->to(site_url('bag/sales'))->with('success', '주문 접수되었습니다.');
    }
}
