<?php

namespace App\Http\Controllers\API\Transaction;

use App\Http\Requests\API\CreateAccountAPIRequest;
use App\Http\Requests\API\UpdateAccountAPIRequest;
use App\Models\Account;
use App\Repositories\AccountRepository;
use Illuminate\Http\Request;
use App\Http\Controllers\AppBaseController;
use Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Carbon\Carbon;
use Auth;

/**
 * Class AccountController
 * @package App\Http\Controllers\API
 */

class TransactionController extends AppBaseController
{

    public function validateRequest($invoiceRules, Request $request){
        
        $input = $request->all();
        $array = json_decode($input['data'], true);

        $validator = Validator::make($input, $invoiceRules);
          //dd($input['data']);
  
         // $request->validate($rules);
          if ($validator->fails()) 
           { 
             throw new \Illuminate\Validation\ValidationException($validator);
             //throw $error;
           }
    }

    public function validateTransactionRequest(Request $request){
        $array = [ 
            'entrytype_id' => 'required|exists:entry_types,id',
            'tr_date' => 'nullable|date|date_format:d-m-Y',
            'cr_total' => 'required|numeric',
            'dr_total' => 'required|numeric',
        ]; 

        $this->validateRequest($array, $request);
    }

    public function validateTransactionItems($array){
        $rules = [
            '*.account_id' => 'required|distinct|exists:accounts,id',
            '*.cr_total' => 'required|numeric',
            '*.dr_total' => 'required|numeric'
        ];  
    }

    public function validateTr($entryType, $entries){
        $dcValid = false;
        foreach($entries as $entry){
            $account = Account::find($entry['account_id']);  
            if($entryType->restriction_bankcash == 4){
                if($account->type != '1'){
                    return $this->sendValidationError('Only bank or cash accounts are allowed for this entry type.');
                }
            }
            if($entryType->restriction_bankcash == 5){
                if($account->type == '1'){
                    return $this->sendValidationError('Bank or cash ledgers are not allowed for this entry type.');
                }
            }   
            $type = $this->checkAmount($entry['cr_total'], $entry['dr_total']);
            if($type == "D"){
                if($entryType->restriction_bankcash == 2){
                    if($account->type == '1'){
                        $dcValid=true;
                    }
                }
            }else if($type == "C"){
                if($entryType->restriction_bankcash == 3){
                    if($account->type == '1'){
                        $dcValid=true;
                    }
                }
            } 
            
        }
        if($entryType->restriction_bankcash == 2){
            if(!$dcValid){
                return $this->sendValidationError('Atleast one bank or cash ledger has to be on debit side for this entry type.');
            }
        }
        if($entryType->restriction_bankcash == 3){
            if(!$dcValid){
                return $this->sendValidationError('Atleast one bank or cash ledger has to be on credit side for this entry type.');
            }
        }
        return null;
           
    }

    public function checkAmount($crAmount, $drAmount){
        if(!empty($crAmount) && ((float)$crAmount)>0){
            return "C";
        }else{
            return "D";
        }
    }

    public function createTransaction(Request $request){
        
        $input = $request->all();
        $this->validateTransactionRequest($request);

        $array = json_decode($input['data'], true);
        $this->validateTransactionItems($array);
        $entryType = \App\Models\EntryType::find($input['entrytype_id']);
        $valid= $this->validateTr($entryType, $array);
        if(!empty($valid)){
            return $valid;
        }
        
        if(!isset($input['ref_number'])){
            $input['ref_number'] = \App\Models\Invoice::generateInvoiceNumber($input['tr_date']);
        }
        if(!isset($input['narration'])){
            $input['narration'] = '';
        }

        $input['tr_date'] = $this->formatDate($input['tr_date']);
        
        try{
        DB::beginTransaction();
        $entryId = DB::table('entries')->insertGetId([
            'entrytype_id' => $input['entrytype_id'],
            'ref_number' => $input['ref_number'],
            'tr_date' => $input['tr_date'],
            'cr_total' => $input['cr_total'],
            'dr_total' => $input['dr_total'],
            'narration' => $input['narration']
        ]);

        foreach( $array as $item){
            DB::table('entryitems')->insert([
                'entry_id' => $entryId,
                'account_id' => $item['account_id'],
                'cr_total' => $item['cr_total'],
                'dr_total' => $item['dr_total'],
            ]); 
        }
        
        DB::commit();
        $entry = \App\Models\Entry::find($entryId);

        return  $this->sendResponse( new  \App\Http\Resources\Transaction\EntryResource($entry), 'Transaction created successfully.');

        } catch (\Exception $e) {
            DB::rollback();
            throw $e;
           // return $this->handleDBException($e);
        } catch (\Throwable $e) {
            DB::rollback();
           // return $this->handleDBException($e);
        }

    }


    public function updateTransaction($entryId, Request $request){
        
        $input = $request->all();
        $this->validateTransactionRequest($request);

        $array = json_decode($input['data'], true);
        $this->validateTransactionItems($array);

        $entryType = \App\Models\EntryType::find($input['entrytype_id']);
        $valid= $this->validateTr($entryType, $array);
        if(!empty($valid)){
            return $valid;
        }

        
        if(!isset($input['ref_number'])){
            $input['ref_number'] = \App\Models\Invoice::generateInvoiceNumber($input['tr_date']);
        }
        if(!isset($input['narration'])){
            $input['narration'] = '';
        }
        $input['tr_date'] = $this->formatDate($input['tr_date']);
        
        unset($input['data']);

        try{
        DB::beginTransaction();

        DB::table('entries')->where('id', $entryId)->update($input);

        DB::table('entryitems')->where('entry_id', $entryId)->delete();

        foreach( $array as $item){
            DB::table('entryitems')->insert([
                'entry_id' => $entryId,
                'account_id' => $item['account_id'],
                'cr_total' => $item['cr_total'],
                'dr_total' => $item['dr_total'],
                'created_at' => \Carbon\Carbon::now(),
            ]); 
        }
        
        DB::commit();
        $entry = \App\Models\Entry::find($entryId);

        return  $this->sendResponse( new  \App\Http\Resources\Transaction\EntryResource($entry), 'Transaction created successfully.');

        } catch (\Exception $e) {
            DB::rollback();
            throw $e;
           // return $this->handleDBException($e);
        } catch (\Throwable $e) {
            DB::rollback();
           // return $this->handleDBException($e);
        }

    }

    public function deleteTransaction($entryId){
        $transaction = \App\Models\Entry::find($entryId);
        if($transaction){
            $transaction->delete();
        }
        return $this->sendResponseMessage('Transaction deleted succesfully');
    }

    public function formatDate($date){
        return Carbon::createFromFormat('d-m-Y', $date)->format('Y-m-d');
    }

    public function viewTransaction($entryId){
        $invoice = \App\Models\Entry::find($entryId); 
        if(empty($invoice)){
            $this->sendValidationError('Transaction not found');
        }
        return $this->sendDataResponse(new \App\Http\Resources\Transaction\EntryResource($invoice));
    }

    public function listTransaction(Request $request){
        $type = $request->get('type');
        $query = $request->get('query');
        $invoices =null;
        $user = Auth::user();
        if ($user->hasPermission('limitlist.transaction')) { // you can pass an id or slug
            $consumptions = \App\Models\Entry::orderBy('created_at','DESC')->where('created_by',$user->id)->take(config('app_data.limit_list_count'))->get();
            return  new \App\Http\Resources\LimitlistPaginationResourceCollection($consumptions, \App\Http\Resources\Transaction\EntryResource::class);      
        }else{
            if(!empty($type) && !empty($query)){
                $t1 = \App\Models\EntryType::where('name','=',$type)->first();
                $ids = \App\Models\Account::where('name','LIKE', '%'.$query.'%')->pluck('id')->toArray();
                $entryIds = \App\Models\EntryItem::whereIn('account_id', $ids)->pluck('entry_id')->toArray();
    
                $invoices = \App\Models\Entry::where('entrytype_id','=', $t1->id)->where(function ($query) use ($entryIds){
                    $query->whereIn('id', $entryIds);
                })->orderBy('tr_date','DESC')->paginate(config('app_data.per_page_data'));
    
            }elseif(empty($type) && !empty($query)){
                $ids = \App\Models\Account::where('name','LIKE', '%'.$query.'%')->pluck('id')->toArray();
                $entryIds = \App\Models\EntryItem::whereIn('account_id', $ids)->pluck('entry_id')->toArray();
    
                $invoices = \App\Models\Entry::whereIn('id', $entryIds)->orderBy('tr_date','DESC')->paginate(config('app_data.per_page_data'));
    
            }else if(empty($query) && !empty($type)){
                $t1 = \App\Models\EntryType::where('name','=',$type)->first();
                $invoices = \App\Models\Entry::where('entrytype_id','=', $t1->id)->orderBy('tr_date','DESC')->paginate(config('app_data.per_page_data'));
            }else{
                $invoices = \App\Models\Entry::orderBy('tr_date', 'DESC')->paginate(config('app_data.per_page_data'));
            }
        }


        
        
        return  new \App\Http\Resources\BasePaginationResourceCollection($invoices, collect($invoices->items()), \App\Http\Resources\Transaction\EntryResource::class);
    }
}