<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Illuminate\Http\Request;

use App\Models\Material;
use App\Models\MaterialsPicture;
use App\Models\MaterialsFile;
use App\Models\MaterialsType;
use App\Models\MaterialsBrand;
use App\Models\MaterialsFinish;
use App\Models\MaterialsIdentifier;
use App\Models\MaterialsUnitsSoldBy;
use App\Models\MaterialsStatus;

use App\Models\MeasurementsType;

use App\Models\PropertiesLocation;
use App\Models\UnitsLocation;

use App\Models\UsersRole;
use App\Models\User;
use Carbon\Carbon;

use App\Libraries\Generic;


class MaterialsMeasurementsController extends Controller
{
    
    protected $generic;
    
    public function __construct(){
        
        $this->generic = new Generic();
        
    }
    
    // materials related functions
    
    public function material(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('add-edit-material')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }

        $validator = Validator::make($request->all(), [
            'name' => 'required',
            'material_status_id' => 'required',
            'material_type_id' => 'required'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        $update_criteria = [];
        if(!empty($request->id)){
            $update_criteria['id'] = $request->id;
        }
        else{
            $update_criteria['id'] = 0;
        }
        
        $material = Material::updateOrCreate(
            $update_criteria,
            [
                'name' => $request->name, 
                'material_status_id' => $request->material_status_id, 
                'material_type_id' => $request->material_type_id, 
                'material_brand_id' => $request->material_brand_id ?? null,
                'color' => $request->color ?? '',
                'material_finish_id' => $request->material_finish_id ?? null,
                'material_identifier_id' => $request->material_identifier_id ?? null,
                'material_vendor_id' => $request->material_vendor_id ?? null,
                'website' => $request->website ?? '',
                'material_unit_sold_by_id' => $request->material_unit_sold_by_id ?? null,
                'coverage_per_unit' => $request->coverage_per_unit ?? '',
                'material_coverage_unit_id' => $request->material_coverage_unit_id ?? null,
                'last_purchased' => $request->last_purchased ?? '',
                'units_purchased' => $request->units_purchased ?? '',
                'price_per_unit' => $request->price_per_unit ?? '',
                'coverage_purchased' => $request->coverage_purchased ?? '',
                'material_on_hand' => $request->material_on_hand ?? '',
                'coverage_on_hand' => $request->coverage_on_hand ?? '',
                'property_location_id' => $request->property_location_id ?? null,
                'notes' => $request->notes ?? '',
                'owner_id' => $owner_id,
                'created_by' => $user_id
            ]
        );
        
        $material_id = $material->id;
        
        // pictures
        $pictures = $request->pictures ?? [];

        foreach($pictures as $p){
            
            $update_criteria = [];
            if(!empty($p['id'])){
                $update_criteria['id'] = $p['id'];
            }
            else{
                $update_criteria['id'] = 0;
            }
            
            MaterialsPicture::updateOrCreate($update_criteria, [
                'material_id' => $material_id,
                'picture' => $p['picture'],
                'order_number' => $p['order_number']  ?? 1
            ]);
        }
        
        // files
        
        $files = $request->material_files ?? [];

        foreach($files as $f){
            
            $update_criteria = [];
            if(!empty($f['id'])){
                $update_criteria['id'] = $f['id'];
            }
            else{
                $update_criteria['id'] = 0;
            }
            
            MaterialsFile::updateOrCreate($update_criteria, [
                'material_id' => $material_id,
                'title' => $f['title'] ?? '',
                'file' => $f['file']
            ]);
        }
        
        return response()->json(['message' => 'Success', 'data'=> [] ]);

    }
    
    public function getMyMaterials(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('get-my-materials')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        $type_id = $request->type_id;
        
        $where = [
            'materials.owner_id' => $owner_id,
        ];
        
        if(!empty($type_id)){
            $where['material_type_id'] = $type_id;
        }
        
        $materials = Material::
                            select(['materials.*', 'materials_statuses.status as material_status', 'materials_types.type  as material_type', 'materials_brands.brand as material brand', 'materials_finishes.finish as material_finish', 'materials_identifiers.identifier as material_identifier', 'materials_units_sold_bys.sold_by as maetrial_unit_sold_by', 'materials_coverage_units.unit as material_coverage_unit', 'properties_locations.location as property_location'])
                            ->leftjoin('materials_statuses', 'materials.material_status_id', '=', 'materials_statuses.id')
                            ->leftjoin('materials_types', 'materials.material_type_id', '=', 'materials_types.id')
                            ->leftjoin('materials_brands', 'materials.material_brand_id', '=', 'materials_brands.id')
                            ->leftjoin('materials_finishes', 'materials.material_finish_id', '=', 'materials_finishes.id')
                            ->leftjoin('materials_identifiers', 'materials.material_identifier_id', '=', 'materials_identifiers.id')
                            ->leftjoin('materials_units_sold_bys', 'materials.material_unit_sold_by_id', '=', 'materials_units_sold_bys.id')
                            ->leftjoin('materials_coverage_units', 'materials.material_coverage_unit_id', '=', 'materials_coverage_units.id')
                            ->leftjoin('properties_locations', 'materials.property_location_id', '=', 'properties_locations.id')
                            ->where($where)
                            ->get();

        
        return response()->json(['message' => 'Success', 'data'=> $materials ]);

    }
    
    public function getMaterial(Request $request)
    {
        
        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);
        
        // check if permission to do
        if(!User::checkPermission('get-material')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        $material_id = $request->query('material_id');
        $material = Material::find($material_id);
        
        // check if property exists
        if(empty($material)){
            return response()->json(['message' => 'No material found']);
        }
        
        // check if have access to view or edit
        if($material->owner_id != $owner_id){
            return response()->json(config('constants.messages.invalid_access'), 400);
            exit();
        }

        $material = Material::
                        select(['materials.*', 'materials_statuses.status as material_status', 'materials_types.type  as material_type', 'materials_brands.brand as material brand', 'materials_finishes.finish as material_finish', 'materials_identifiers.identifier as material_identifier', 'materials_units_sold_bys.sold_by as maetrial_unit_sold_by', 'materials_coverage_units.unit as material_coverage_unit', 'properties_locations.location as property_location'])
                        ->leftjoin('materials_statuses', 'materials.material_status_id', '=', 'materials_statuses.id')
                        ->leftjoin('materials_types', 'materials.material_type_id', '=', 'materials_types.id')
                        ->leftjoin('materials_brands', 'materials.material_brand_id', '=', 'materials_brands.id')
                        ->leftjoin('materials_finishes', 'materials.material_finish_id', '=', 'materials_finishes.id')
                        ->leftjoin('materials_identifiers', 'materials.material_identifier_id', '=', 'materials_identifiers.id')
                        ->leftjoin('materials_units_sold_bys', 'materials.material_unit_sold_by_id', '=', 'materials_units_sold_bys.id')
                        ->leftjoin('materials_coverage_units', 'materials.material_coverage_unit_id', '=', 'materials_coverage_units.id')
                        ->leftjoin('properties_locations', 'materials.property_location_id', '=', 'properties_locations.id')
                        ->where('materials.id', $material_id)
                        ->with('pictures', 'files')
                        ->get();
        
        return response()->json(['data' => $material]);
    }
    
    public function deleteMaterial(Request $request)
    {
        
        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);
        
        // check if permission to do
        if(!User::checkPermission('delete-material')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        $material_id = $request->query('material_id');
        $material = Material::find($material_id);
        
        // check if property exists
        if(empty($material)){
            return response()->json(['message' => 'No material found']);
        }
        
        // check if have access to view or edit
        if($material->owner_id != $owner_id){
            return response()->json(config('constants.messages.invalid_access'), 400);
            exit();
        }

        Material::find($material_id)->delete();
        
        return response()->json(['message' => 'Deleted', 'data'=> [] ]);
        
    }
    
    // --------------------- Bulk Actions Start --------------------------------
    
    public function changeMaterialsStatus(Request $request){
        
        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);
        
        // check if permission to do
        if(!User::checkPermission('change-materials-status')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        $validator = Validator::make($request->all(), [
            'ids' => 'required',
            'material_status_id' => 'required'
        ]);
        
        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        $ids = $request->ids;
        $material_status_id = $request->material_status_id;
        
        foreach($ids as $id){
            Material::where(['id'=>$id])->update(['material_status_id'=>$material_status_id]);
        }
        
        return response()->json(['message' => 'Updated Successfully']);
        
    }
    
    // --------------------- Bulk Actions End --------------------------------
    
    public function materialType(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('material-type')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }

        $validator = Validator::make($request->all(), [
            'type' => 'required'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        
        $update_criteria = [];
        if(!empty($request->id)){
            $update_criteria['id'] = $request->id;
        }
        else{
            $update_criteria['id'] = 0;
        }
        
        MaterialsType::updateOrCreate(
            $update_criteria,
            [
                'type' => $request->type, 
                'owner_id' => $owner_id
            ]
        );
        
        return response()->json(['message' => 'Success', 'data'=> [] ]);

    }
    
    public function getMaterialTypes(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('get-material-types')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        $materials_types = MaterialsType::where(['owner_id' => $owner_id])->get();

        
        return response()->json(['message' => 'Success', 'data'=> $materials_types ]);

    }
    
    public function materialBrand(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('material-brand')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }

        $validator = Validator::make($request->all(), [
            'brand' => 'required'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        $update_criteria = [];
        if(!empty($request->id)){
            $update_criteria['id'] = $request->id;
        }
        else{
            $update_criteria['id'] = 0;
        }
        
        MaterialsBrand::updateOrCreate(
            $update_criteria,
            [
                'brand' => $request->brand, 
                'owner_id' => $owner_id
            ]
        );
        
        return response()->json(['message' => 'Success', 'data'=> [] ]);

    }
    
    public function getMaterialBrands(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('get-material-brands')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        $materials_brands = MaterialsBrand::where(['owner_id' => $owner_id])->get();

        
        return response()->json(['message' => 'Success', 'data'=> $materials_brands ]);

    }
    
    public function materialFinish(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('material-finish')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }

        $validator = Validator::make($request->all(), [
            'finish' => 'required'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        $update_criteria = [];
        if(!empty($request->id)){
            $update_criteria['id'] = $request->id;
        }
        else{
            $update_criteria['id'] = 0;
        }
        
        MaterialsFinish::updateOrCreate(
            $update_criteria,
            [
                'finish' => $request->finish, 
                'owner_id' => $owner_id
            ]
        );
        
        return response()->json(['message' => 'Success', 'data'=> [] ]);

    }
    
    public function getMaterialFinishes(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('get-material-finishes')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        $materials_finishes = MaterialsFinish::where(['owner_id' => $owner_id])->get();

        
        return response()->json(['message' => 'Success', 'data'=> $materials_finishes ]);

    }
    
    public function materialIdentifier(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('material-identifier')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }

        $validator = Validator::make($request->all(), [
            'identifier' => 'required'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        $update_criteria = [];
        if(!empty($request->id)){
            $update_criteria['id'] = $request->id;
        }
        else{
            $update_criteria['id'] = 0;
        }
        
        MaterialsIdentifier::updateOrCreate(
            $update_criteria,
            [
                'identifier' => $request->identifier, 
                'owner_id' => $owner_id
            ]
        );
        
        return response()->json(['message' => 'Success', 'data'=> [] ]);

    }
    
    public function getMaterialIdentifiers(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('get-material-identifiers')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        $materials_identifiers = MaterialsIdentifier::where(['owner_id' => $user_id])->get();

        
        return response()->json(['message' => 'Success', 'data'=> $materials_identifiers ]);

    }
    
    public function getMaterialStatuses(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(empty($user_id)){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        $statuses = MaterialsStatus::get();

        
        return response()->json(['message' => 'Success', 'data'=> $statuses ]);

    }
    
    
    // measurements related functions
    
    public function measurementType(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('measurement-type')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }

        $validator = Validator::make($request->all(), [
            'type' => 'required'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        
        $update_criteria = [];
        if(!empty($request->id)){
            $update_criteria['id'] = $request->id;
        }
        else{
            $update_criteria['id'] = 0;
        }
        
        MeasurementsType::updateOrCreate(
            $update_criteria,
            [
                'type' => $request->type, 
                'owner_id' => $owner_id
            ]
        );
        
        return response()->json(['message' => 'Success', 'data'=> [] ]);

    }
    
    public function getMeasurementTypes(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('get-measurement-types')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        $measurements_types = MeasurementsType::where(['owner_id' => $owner_id])->get();

        
        return response()->json(['message' => 'Success', 'data'=> $measurements_types ]);

    }
    
    public function propertiesLocation(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('properties-location')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }

        $validator = Validator::make($request->all(), [
            'location' => 'required'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        $update_criteria = [];
        if(!empty($request->id)){
            $update_criteria['id'] = $request->id;
        }
        else{
            $update_criteria['id'] = 0;
        }
        
        PropertiesLocation::updateOrCreate(
            $update_criteria,
            [
                'location' => $request->location, 
                'owner_id' => $owner_id
            ]
        );
        
        return response()->json(['message' => 'Success', 'data'=> [] ]);

    }
    
    public function getPropertiesLocations(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('get-properties-locations')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        $validator = Validator::make($request->all(), [
            'property_id' => 'required'
        ]);
        
        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        $property_id = $request->property_id;
        
        $properties_locations = PropertiesLocation::where(['owner_id' => $owner_id, 'property_id' => $property_id])->get();

        
        return response()->json(['message' => 'Success', 'data'=> $properties_locations ]);

    }
    
    
    ///////
    
    public function unitsLocation(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('units-location')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }

        $validator = Validator::make($request->all(), [
            'location' => 'required'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        $update_criteria = [];
        if(!empty($request->id)){
            $update_criteria['id'] = $request->id;
        }
        else{
            $update_criteria['id'] = 0;
        }
        
        UnitsLocation::updateOrCreate(
            $update_criteria,
            [
                'location' => $request->location, 
                'owner_id' => $owner_id
            ]
        );
        
        return response()->json(['message' => 'Success', 'data'=> [] ]);

    }
    
    public function getUnitsLocations(Request $request){

        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);

        // check if permission to do
        if(!User::checkPermission('get-units-locations')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        $validator = Validator::make($request->all(), [
            'unit_id' => 'required'
        ]);
        
        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        $unit_id = $request->unit_id;
        
        $units_locations = UnitsLocation::where(['owner_id' => $owner_id, 'unit_id' => $unit_id])->get();

        
        return response()->json(['message' => 'Success', 'data'=> $units_locations ]);

    }
    


}