import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Param,
  Body,
  HttpException,
  HttpStatus,
  NotFoundException,
  Query,
  Res,
} from '@nestjs/common';
import { DataSource } from 'typeorm';
import { CompaniesService } from './companies.service';
import { Companies } from '../companies/entities/companies.entity';
import { Public } from '../auth/public.decorator';
import {
  ApiBearerAuth,
  ApiTags,
  ApiBody,
  ApiParam,
  ApiQuery,
  ApiOperation,
} from '@nestjs/swagger';

@ApiTags('companies')
@ApiBearerAuth('access-token')
@Controller('companies')
export class CompaniesController {
  constructor(
    private readonly companyService: CompaniesService,
    private readonly dataSource: DataSource,
  ) {}
  // Get companies for admin approval
  @Public()
  @Get('applications')
  @ApiOperation({ summary: 'Get Company Applications' })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  @ApiQuery({ name: 'status', required: false, type: String })
  @ApiQuery({ name: 'search', required: false, type: String })
  async getCompaniesForApproval(
    @Query('page') page: number = 1,
    @Query('limit') limit: number = 10,
    @Query('status') status?: string,
    @Query('search') search?: string,
  ) {
    return this.companyService.getCompaniesForApproval(
      Number(page),
      Number(limit),
      status,
      search,
    );
  }

  // Approve company
  @Public()
  @Put('approve/:companyId')
  @ApiOperation({ summary: 'Approve company' })
  @ApiParam({ name: 'companyId', type: Number })
  async approveCompany(@Param('companyId') companyId: number) {
    try {
      return await this.companyService.approveCompany(Number(companyId));
    } catch (error) {
      throw new HttpException(
        error.message || 'Failed to approve company',
        HttpStatus.BAD_REQUEST,
      );
    }
  }

  // Reject company
  @Public()
  @Put('reject/:companyId')
  @ApiOperation({ summary: 'Reject company' })
  @ApiParam({ name: 'companyId', type: Number })
  async rejectCompany(@Param('companyId') companyId: number) {
    try {
      return await this.companyService.rejectCompany(Number(companyId));
    } catch (error) {
      throw new HttpException(
        error.message || 'Failed to reject company',
        HttpStatus.BAD_REQUEST,
      );
    }
  }
  @Public()
  @Get('by_user/:userId')
  @ApiOperation({ summary: 'Get company by user ID' })
  @ApiParam({ name: 'userId', type: Number })
  async getCompanyByUser(@Param('userId') userId: number) {
    // First check if user exists and get their role
    const user = await this.dataSource.query(
      'SELECT id, role FROM users WHERE id = ? LIMIT 1',
      [userId],
    );

    if (!user[0]) {
      throw new NotFoundException('User not found');
    }

    // If user is a seeker, return appropriate response
    if (user[0].role === 'seeker') {
      return {
        success: false,
        message: 'User is a seeker, no company associated',
        data: null,
      };
    }

    // For recruiters/admins, look for company
    const company = await this.dataSource.query(
      'SELECT * FROM companies WHERE user_id = ? LIMIT 1',
      [userId],
    );

    if (!company[0]) {
      return {
        success: false,
        message: 'No company found for this user',
        data: null,
      };
    }

    return {
      success: true,
      data: company[0],
    };
  }

  //  NEW: Admin adds company + recruiter user
  // @Public()
  // @Post('add_admin_company')
  // async addAdminCompany(@Body() payload: any) {
  //   try {
  //     console.log('Controller received payload:', payload);
  //     return await this.companyService.addAdminCompany(
  //       payload,
  //       payload.requester_id,
  //     );
  //   } catch (error) {
  //     throw new HttpException(
  //       error.message || 'Failed to create company and recruiter',
  //       HttpStatus.BAD_REQUEST,
  //     );
  //   }
  // }
  @Public()
  @Post('add_admin_company')
  @ApiOperation({ summary: 'Add Admin Company' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        // Recruiter User Details
        full_name: { type: 'string', example: 'John Recruiter' },
        username: { type: 'string', example: 'john_recruiter' },
        email: {
          type: 'string',
          format: 'email',
          example: 'recruiter@company.com',
        },
        phone: { type: 'string', example: '+1234567890' },
        password: { type: 'string', example: 'securePass123' },

        // Company Details
        name: { type: 'string', example: 'Tech Corp' },
        website: { type: 'string', example: 'https://techcorp.com' },
        logo: { type: 'string', example: 'https://example.com/logo.png' },
        banner_url: {
          type: 'string',
          example: 'https://example.com/banner.png',
        },
        about: { type: 'string', description: 'Company description' },
        vision: { type: 'string', description: 'Company vision' },
        founded_at: { type: 'string', format: 'date', example: '2020-01-01' },
        location: { type: 'string', example: 'San Francisco, CA' },
        industry_id: { type: 'number', example: 1 },
        company_size_id: { type: 'number', example: 2 },
        organization_type_id: { type: 'number', example: 3 },
        country_id: { type: 'number', example: 101 },
        state_id: { type: 'number', example: 10 },
        city_id: { type: 'number', example: 5 },
        area_id: { type: 'number', example: 50 },
        pincode: { type: 'string', example: '94105' },
        latitude: { type: 'number', example: 37.7749 },
        longitude: { type: 'number', example: -122.4194 },
        gst_number: { type: 'string', example: 'GST123456789' },
        cin_number: { type: 'string', example: 'CIN123456789' },
        social_links: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              platform_id: { type: 'number' },
              url: { type: 'string' },
            },
          },
        },
      },
      required: ['full_name', 'email', 'password', 'name'],
    },
  })
  async addAdminCompany(@Body() payload: any) {
    try {
      console.log('Controller received payload:', payload);
      return await this.companyService.addAdminCompany(
        payload,
        payload.requester_id,
      );
    } catch (error) {
      throw new HttpException(
        error.message || 'Failed to create company and recruiter',
        HttpStatus.BAD_REQUEST,
      );
    }
  }

  @Public()
  @Put('toggle_status/:companyId')
  @ApiOperation({ summary: 'Toggle company status' })
  @ApiParam({ name: 'companyId', type: Number })
  async toggleStatus(@Param('companyId') companyId: number, @Res() res) {
    try {
      const result = await this.companyService.toggleCompanyStatus(companyId);
      return res.status(HttpStatus.OK).json(result);
    } catch (error) {
      return res.status(HttpStatus.BAD_REQUEST).json({
        success: false,
        message: error.message || 'Failed to toggle status',
      });
    }
  }

  @Public()
  @Get('all_with_pagination')
  @ApiOperation({ summary: 'Get all companies paginated' })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  @ApiQuery({ name: 'search', required: false, type: String })
  async findAllPaginated(
    @Query('page') page: number = 1,
    @Query('limit') limit: number = 10,
    @Query('search') search?: string,
  ) {
    return this.companyService.findAllPaginated(
      Number(page),
      Number(limit),
      search,
    );
  }
  @Public()
  @Get(':id/details')
  @ApiOperation({ summary: 'Get company details with open jobs' })
  @ApiParam({ name: 'id', type: Number })
  @ApiQuery({ name: 'page', required: false, type: String })
  @ApiQuery({ name: 'limit', required: false, type: String })
  async getCompanyDetails(
    @Param('id') id: number,
    @Query('page') page: string = '1',
    @Query('limit') limit: string = '9',
  ) {
    return this.companyService.findOneWithOpenJobs(
      Number(id),
      Number(page),
      Number(limit),
    );
  }
  @Public()
  @Get()
  @ApiOperation({ summary: 'Get all companies' })
  async findAll(): Promise<Companies[]> {
    return this.companyService.findAll();
  }

  @Public()
  @Get('with_open_positions')
  @ApiOperation({ summary: 'Get companies with open positions' })
  async findAllWithOpenPositions(): Promise<any[]> {
    return this.companyService.findAllWithOpenPositions();
  }

  @Public()
  @Get('filtered')
  @ApiOperation({ summary: 'Filter Companies' })
  @ApiQuery({
    name: 'search',
    required: false,
    type: String,
    description: 'Search by name, city, state, country',
  })
  @ApiQuery({
    name: 'industry',
    required: false,
    type: String,
    description: 'Exact industry name',
  })
  @ApiQuery({ name: 'organizationType', required: false, type: String })
  @ApiQuery({ name: 'companySize', required: false, type: String })
  @ApiQuery({ name: 'country', required: false, type: String })
  @ApiQuery({ name: 'state', required: false, type: String })
  @ApiQuery({ name: 'city', required: false, type: String })
  @ApiQuery({
    name: 'featured',
    required: false,
    enum: ['featured', 'non-featured'],
  })
  @ApiQuery({
    name: 'positions',
    required: false,
    type: String,
    description: 'Minimum number of open positions',
  })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  @ApiQuery({
    name: 'excludeAdmin',
    required: false,
    type: Boolean,
    description: 'Exclude admin-seeded companies',
  })
  async findFilteredCompanies(
    @Query('search') search?: string,
    @Query('industry') industry?: string,
    @Query('organizationType') organizationType?: string,
    @Query('companySize') companySize?: string,
    @Query('country') country?: string,
    @Query('state') state?: string,
    @Query('city') city?: string,
    @Query('featured') featured?: string,
    @Query('positions') positions?: string,
    @Query('excludeAdmin') excludeAdmin?: string,
    @Query('page') page: string = '1',
    @Query('limit') limit: string = '10',
  ): Promise<{
    data: any[];
    total: number;
    page: number;
    limit: number;
    totalPages: number;
  }> {
    return this.companyService.findFilteredCompanies({
      search,
      industry,
      organizationType,
      companySize,
      country,
      state,
      city,
      featured,
      positions,
      excludeAdmin,
      page: Number(page),
      limit: Number(limit),
    });
  }

  @Public()
  @Get('filter_options')
  @ApiOperation({ summary: 'Get company filter options' })
  async getFilterOptions(): Promise<any> {
    return this.companyService.getFilterOptions();
  }

  // Get companies for job post dropdown (admin gets ONLY dummy companies where is_admin_company = 1)
  @Public()
  @Get('for_job_post')
  @ApiOperation({ summary: 'Get companies for job post' })
  @ApiQuery({ name: 'userRole', required: false, type: String })
  async getCompaniesForJobPost(
    @Query('userRole') userRole?: string,
    @Query('page') page: number = 1,
    @Query('limit') limit: number = 10,
    @Query('search') search?: string,
  ): Promise<any> {
    return this.companyService.getCompaniesForJobPost(
      userRole,
      Number(page),
      Number(limit),
      search,
    );
  }

  @Public()
  @Get('my_profile')
  @ApiOperation({ summary: 'Get my company profile' })
  @ApiQuery({ name: 'userId', type: Number })
  async getMyProfile(@Query('userId') userId: number): Promise<Companies> {
    const companyId = await this.companyService.findCompanyIdByUserId(userId);
    if (!companyId) {
      throw new NotFoundException('Company not found for this user');
    }
    return this.companyService.findOne(companyId);
  }
  @Get(':id')
  @ApiOperation({ summary: 'Get company by ID' })
  @ApiParam({ name: 'id', type: Number })
  async findOne(@Param('id') id: number): Promise<Companies> {
    const company = await this.companyService.findOne(Number(id));
    if (!company) {
      throw new HttpException('Company not found', HttpStatus.NOT_FOUND);
    }
    return company;
  }

  @Public()
  @Post()
  @ApiOperation({ summary: 'Create Company' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        name: { type: 'string', example: 'New Company Inc' },
        about: { type: 'string' },
        website: { type: 'string' },
        logo: { type: 'string', description: 'URL' },
        banner_url: { type: 'string', description: 'URL' },
        company_size_id: { type: 'number' },
        organization_type_id: { type: 'number' },
        industry_id: { type: 'number' },
        country_id: { type: 'number' },
        state_id: { type: 'number' },
        city_id: { type: 'number' },
        address: { type: 'string' },
        gst_number: { type: 'string' },
        cin_number: { type: 'string' },
        email: { type: 'string', format: 'email' },
        phone: { type: 'string' },
        social_links: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              platform_id: { type: 'number' },
              url: { type: 'string' },
            },
          },
        },
      },
      required: ['name'],
    },
  })
  async create(@Body() companyData: Partial<Companies>): Promise<Companies> {
    try {
      return await this.companyService.create(companyData);
    } catch (error) {
      throw new HttpException(
        error.message || 'Failed to create company',
        HttpStatus.BAD_REQUEST,
      );
    }
  }

  // Create admin dummy company (admin only)
  // NOTE: Commented out because dummy companies are hardcoded in SQL migration file
  // @Public()
  // @Post('admin/dummy')
  // async createAdminDummyCompany(
  //   @Body() body: { userRole?: string; companyData: Partial<Companies> },
  // ): Promise<any> {
  //   const { userRole, companyData } = body;

  //   if (userRole !== 'admin') {
  //     throw new HttpException(
  //       'Only admins can create dummy companies',
  //       HttpStatus.FORBIDDEN,
  //     );
  //   }

  //   try {
  //     return await this.companyService.createAdminDummyCompany(companyData);
  //   } catch (error) {
  //     throw new HttpException(
  //       error.message || 'Failed to create admin dummy company',
  //       HttpStatus.BAD_REQUEST,
  //     );
  //   }
  // }

  @Put(':id')
  @ApiOperation({ summary: 'Update Company' })
  @ApiParam({ name: 'id', type: Number })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        name: { type: 'string' },
        about: { type: 'string' },
        vision: { type: 'string' },
        website: { type: 'string' },
        logo: { type: 'string' },
        banner_url: { type: 'string' },
        company_size_id: { type: 'number' },
        organization_type_id: { type: 'number' },
        industry_id: { type: 'number' },
        country_id: { type: 'number' },
        state_id: { type: 'number' },
        city_id: { type: 'number' },
        location: { type: 'string' },
        pincode: { type: 'string' },
        latitude: { type: 'number' },
        longitude: { type: 'number' },
        gst_number: { type: 'string' },
        cin_number: { type: 'string' },
        featured: { type: 'number', example: 1 },
        status: { type: 'number', example: 1 },
      },
    },
  })
  async update(
    @Param('id') id: number,
    @Body() companyData: Partial<Companies>,
  ): Promise<Companies> {
    try {
      const existing = await this.companyService.findOne(id);
      if (!existing) {
        throw new HttpException('Company not found', HttpStatus.NOT_FOUND);
      }
      return await this.companyService.update(Number(id), companyData);
    } catch (error) {
      throw new HttpException(
        'Failed to update company',
        HttpStatus.BAD_REQUEST,
      );
    }
  }

  @Delete(':id')
  @ApiOperation({ summary: 'Delete company' })
  @ApiParam({ name: 'id', type: Number })
  async remove(@Param('id') id: number): Promise<{ message: string }> {
    const existing = await this.companyService.findOne(id);
    if (!existing) {
      throw new HttpException('Company not found', HttpStatus.NOT_FOUND);
    }

    await this.companyService.remove(Number(id));
    return { message: 'Company deleted successfully' };
  }

  @Public()
  @Get('check_name/:name')
  @ApiOperation({ summary: 'Check company name availability' })
  @ApiParam({ name: 'name', type: String })
  async checkNameAvailability(
    @Param('name') name: string,
  ): Promise<{ available: boolean }> {
    try {
      const existingCompany =
        await this.companyService.checkNameAvailability(name);
      return { available: !existingCompany };
    } catch (error) {
      throw new HttpException(
        'Failed to check company name availability',
        HttpStatus.BAD_REQUEST,
      );
    }
  }
}
