<?php

namespace Modules\Internal\Http\Controllers\Api;

use App\Exceptions\ImportRowException;
use App\Helpers\Helper;
use App\Http\Resources\MemberDataTableResource;
use App\Models\Corporate;
use App\Models\Member;
use Box\Spout\Reader\Common\Creator\ReaderEntityFactory;
use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
use Box\Spout\Common\Entity\Row;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Storage;
use Modules\Internal\Services\MemberEnrollmentService;

class CorporateMemberController extends Controller
{
    public function __construct(MemberEnrollmentService $memberEnrollmentService)
    {
        $this->memberEnrollmentService = $memberEnrollmentService;
    }
    /**
     * Display a listing of the resource.
     * @return Renderable
     */
    public function index(Request $request, $corporate_id)
    {
        $members = Member::query()
            ->filter($request->all())
            // ->where('corporate_id', $corporate_id)
            ->whereHas('employeds', function ($employeds) use ($corporate_id) {
                $employeds->where('corporate_id', $corporate_id);
            })
            ->with([
                'employeds',
                'currentPolicy',
                // 'claims',
                'claims' => function ($claim) {
                    return $claim->whereBetween('requested_at', [now()->startOfYear(), now()->endOfYear()]);
                    // return $claim->used(now()->startOfYear(), now()->endOfYear());
                }
            ])
            ->with('currentPlan')
            // ->with
            ->paginate()
            ->appends($request->all());

        return Helper::paginateResources(MemberDataTableResource::collection($members));
    }

    public function activation(Request $request, $member_id)
    {
        $request->validate([
            'active' => 'required'
        ]);

        // abort(404);

        $member = Member::findOrFail($member_id);
        $member->active = $request->active == '1';

        if ($member->save()) {
            return response()->json([
                'member' => $member,
                'message' => 'Status Updated Successfully'
            ]);
        }
    }

    /**
     * Show the form for creating a new resource.
     * @return Renderable
     */
    public function create()
    {
        return view('internal::create');
    }

    /**
     * Store a newly created resource in storage.
     * @param Request $request
     * @return Renderable
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Show the specified resource.
     * @param int $id
     * @return Renderable
     */
    public function show($id)
    {
        return view('internal::show');
    }

    /**
     * Show the form for editing the specified resource.
     * @param int $id
     * @return Renderable
     */
    public function edit($id)
    {
        return view('internal::edit');
    }

    /**
     * Update the specified resource in storage.
     * @param Request $request
     * @param int $id
     * @return Renderable
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     * @param int $id
     * @return Renderable
     */
    public function destroy($id)
    {
        //
    }


    public function import(Request $request, $corporate_id)
    {
        $request->validate([
            'file' => 'required|file|mimes:xls,xlsx,csv,txt',
        ]);
        $corporate = Corporate::findOrFail($corporate_id)->load('currentPolicy');

        $file_name = now()->getPreciseTimestamp(3) . '-' . $request->file('file')->getClientOriginalName();
        $file = $request->file('file')->storeAs('temp', $file_name);

        $reader = ReaderEntityFactory::createReaderFromFile(Storage::path('temp/' . $file_name));
        $reader->open(Storage::path('temp/' . $file_name));

        $writer = WriterEntityFactory::createXLSXWriter();
        $writer->openToFile(Storage::disk('public')->path('temp/result-' . $file_name));

        $headers_map_to_table_fields = $this->memberEnrollmentService->doc_headers_to_field_map;

        // Write Header to File with certain Format from MemberEnrollmentService::$result_doc_headers
        $result_headers = $this->memberEnrollmentService->result_doc_headers;
        $singleRow = WriterEntityFactory::createRow($this->memberEnrollmentService->makeResultRow($result_headers));
        $writer->addRow($singleRow);

        $imported_member_data = 0;
        $failed_member_data = [];
        foreach ($reader->getSheetIterator() as $sheet) {
            $doc_headers_indexes = [];
            foreach ($sheet->getRowIterator() as $index => $row) {
                if ($index == 1) { // First Row Must be Header
                    foreach ($row->getCells() as $index => $cell) {
                        // Clear up the string and remove all spaces
                        $title = $cell->getValue();
                        $title = preg_replace("/\r|\n/", " ", $title);
                        $title = preg_replace('/\xc2\xa0/', " ", $title);
                        $title = rtrim($title);
                        $title = ltrim($title);
                        $doc_headers_indexes[$index] = $title;
                    }
                } else { // Next Row Should be Data
                    // Collecting Values from table rows and map it to correct fields
                    $new_member_data = [];
                    foreach ($row->getCells() as $header_index => $cell) {
                        if (isset($headers_map_to_table_fields[$doc_headers_indexes[$header_index]])) {
                            $new_member_data[$headers_map_to_table_fields[$doc_headers_indexes[$header_index]]] = $cell->getValue();
                        }
                    }

                    try {
                        // dd($new_member_data);
                        $rowResponse = $this->memberEnrollmentService->handleImportRow($corporate, $new_member_data);

                        // Write Success Result to File
                        $singleRow = WriterEntityFactory::createRow($this->memberEnrollmentService->makeResultRowWithResultFormat($rowResponse));
                        $writer->addRow($singleRow);
                        $imported_member_data++;
                    } catch (ImportRowException $e) {
                        // Write Data Validation Error to File
                        $new_member_data = array_merge($new_member_data, [
                            'ingestion_code' => $e->getCode(),
                            'ingestion_status' => $e->getMessage(),
                        ]);
                        $singleRow = WriterEntityFactory::createRow($this->memberEnrollmentService->makeResultRowWithResultFormat($new_member_data));
                        $writer->addRow($singleRow);
                        $failed_member_data[] = ['row_number' => $index, 'error' => $e->getMessage()];
                    } catch (\Exception $e) {
                        // Write Server Error to File
                        $new_member_data = array_merge($new_member_data, [
                            'ingestion_code' => $e->getCode(),
                            'ingestion_status' => $e->getMessage(),
                        ]);
                        $singleRow = WriterEntityFactory::createRow($this->memberEnrollmentService->makeResultRowWithResultFormat($new_member_data));
                        $writer->addRow($singleRow);
                        $failed_member_data[] = ['row_number' => $index, 'error' => $e->getMessage()];
                    }
                }
            }

            break; //only read first sheet
        }
        $reader->close();
        $writer->close();
        Storage::delete('temp/' . $file_name);
        // throw(404);

        return [
            'total_success_row' => $imported_member_data,
            'total_failed_row' => count($failed_member_data),
            'failed_row' => $failed_member_data,
            'result_file' => [
                'url' => Storage::disk('public')->url('temp/result-' . $file_name),
                'name' => 'result-' . $file_name,
            ]
        ];
    }
}
