import {inject} from '@loopback/core';
import {
  Count,
  CountSchema,
  Filter,
  FilterExcludingWhere,
  repository,
  Where,
} from '@loopback/repository';
import {
  del,
  get,
  getModelSchemaRef,
  param,
  patch,
  post,
  put,
  Request,
  requestBody,
  response,
  RestBindings,
} from '@loopback/rest';
import fs from 'fs';
import multer from 'multer';
import path from 'path';
import {URL} from '../config/constants';
import {TestimonialMaster} from '../models';
import {TestimonialMasterRepository} from '../repositories';
const BASE_URL = `${URL}/uploads/testimonial-images`;
// const BASE_URL = `${URL}/uploads/testimonial-images`
const FALLBACK_URL = `${BASE_URL}/default.jpg`;

// ✅ helper
function resolveImage(image?: string | null): string {
  if (!image) return FALLBACK_URL;

  if (image.startsWith('http://') || image.startsWith('https://')) {
    return image.trim();
  }

  const filename = path.basename(image);
  const localPath = path.join(
    __dirname,
    '../../uploads/testimonial-images',
    filename,
  );

  if (fs.existsSync(localPath)) {
    return `${BASE_URL}/${filename}`;
  }

  return FALLBACK_URL;
}

export class TestimonialmasterController {
  constructor(
    @repository(TestimonialMasterRepository)
    public testimonialMasterRepository: TestimonialMasterRepository,
  ) { }

  // 📌 multer upload middleware
  private getMulterUpload() {
    const storage = multer.diskStorage({
      destination: (req, file, cb) => {
        const dir = path.join(__dirname, '../../uploads/testimonial-images');
        if (!fs.existsSync(dir)) fs.mkdirSync(dir, {recursive: true});
        cb(null, dir);
      },
      filename: (req, file, cb) => {
        cb(null, Date.now() + '-' + file.originalname);
      },
    });
    return multer({storage});
  }

  // ✅ Upload endpoint: create with profile + property image
  @post('/testimonial-masters/uploads')
  @response(200, {
    description: 'TestimonialMaster with images',
  })
  async createWithImages(
    @inject(RestBindings.Http.REQUEST) request: Request,
  ): Promise<TestimonialMaster> {
    const upload = this.getMulterUpload().fields([
      {name: 'profileImage', maxCount: 1},
      {name: 'propertyImage', maxCount: 1},
    ]);

    return new Promise((resolve, reject) => {
      upload(request, {} as any, async err => {
        if (err) return reject(err);

        const files = (request as any).files as {
          [fieldname: string]: Express.Multer.File[];
        };

        const testimonial = await this.testimonialMasterRepository.create({
          ...request.body,
          profileImage: files?.profileImage?.[0]?.filename || null,
          propertyImage: files?.propertyImage?.[0]?.filename || null,
          lastChanged: new Date().toISOString(), // auto-set current date
          createdAt: new Date().toISOString(),
        });

        resolve(testimonial);
      });
    });
  }

  // ✅ Normal create (no upload)
  @post('/testimonial-masters')
  @response(200, {
    description: 'TestimonialMaster model instance',
    content: {'application/json': {schema: getModelSchemaRef(TestimonialMaster)}},
  })
  async create(
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(TestimonialMaster, {
            title: 'NewTestimonialMaster',
            exclude: ['testimonialId'],
          }),
        },
      },
    })
    testimonialMaster: Omit<TestimonialMaster, 'testimonialId'>,
  ): Promise<TestimonialMaster> {
    return this.testimonialMasterRepository.create(testimonialMaster);
  }

  @get('/testimonial-masters')
  @response(200, {
    description: 'Array of TestimonialMaster model instances',
  })
  async find(
    @param.filter(TestimonialMaster) filter?: Filter<TestimonialMaster>,
  ): Promise<any[]> {
    const data = await this.testimonialMasterRepository.find(filter);
    return data.map(item => ({
      ...item,
      profileImage: resolveImage(item.profileImage),
      propertyImage: resolveImage(item.propertyImage),
    }));
  }

  @get('/testimonial-masters/{id}')
  @response(200, {
    description: 'TestimonialMaster model instance',
  })
  async findById(
    @param.path.number('id') id: number,
    @param.filter(TestimonialMaster, {exclude: 'where'})
    filter?: FilterExcludingWhere<TestimonialMaster>,
  ): Promise<any> {
    const item = await this.testimonialMasterRepository.findById(id, filter);
    return {
      ...item,
      profileImage: resolveImage(item.profileImage),
      propertyImage: resolveImage(item.propertyImage),
    };
  }

  @patch('/testimonial-masters')
  @response(200, {
    description: 'TestimonialMaster PATCH success count',
    content: {'application/json': {schema: CountSchema}},
  })
  async updateAll(
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(TestimonialMaster, {partial: true}),
        },
      },
    })
    testimonialMaster: TestimonialMaster,
    @param.where(TestimonialMaster) where?: Where<TestimonialMaster>,
  ): Promise<Count> {
    return this.testimonialMasterRepository.updateAll(
      testimonialMaster,
      where,
    );
  }

  @patch('/testimonial-masters/{id}')
  @response(204, {
    description: 'TestimonialMaster PATCH success',
  })
  async updateById(
    @param.path.number('id') id: number,
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(TestimonialMaster, {partial: true}),
        },
      },
    })
    testimonialMaster: TestimonialMaster,
  ): Promise<void> {
    await this.testimonialMasterRepository.updateById(id, testimonialMaster);
  }

  @put('/testimonial-masters/{id}')
  @response(204, {
    description: 'TestimonialMaster PUT success',
  })
  async replaceById(
    @param.path.number('id') id: number,
    @requestBody() testimonialMaster: TestimonialMaster,
  ): Promise<void> {
    await this.testimonialMasterRepository.replaceById(id, testimonialMaster);
  }

  @del('/testimonial-masters/{id}')
  @response(204, {
    description: 'TestimonialMaster DELETE success',
  })
  async deleteById(@param.path.number('id') id: number): Promise<void> {
    await this.testimonialMasterRepository.deleteById(id);
  }
}
