import { createAction, Property, OAuth2PropertyValue } from '@activepieces/pieces-framework';
import { bexioAuth } from '../auth';
import { BexioClient } from '../common/client';

export const createProjectAction = createAction({
  auth: bexioAuth,
  name: 'create_project',
  displayName: 'Create Project',
  description: 'Create a new project',
  audience: 'both',
  aiMetadata: { description: 'Creates a new Bexio project linked to a contact, with status, type, responsible user, optional dates, and optional invoicing/budget settings. Use to set up a project before tracking time or billing against it. Requires a name, project status, project type, contact, and user. Not idempotent: each call creates a separate project.', idempotent: false },
  props: {
    document_nr: Property.ShortText({
      displayName: 'Document Number',
      description: 'Project number (required if automatic numbering is disabled)',
      required: false,
    }),
    name: Property.ShortText({
      displayName: 'Project Name',
      description: 'Name of the project',
      required: true,
    }),
    start_date: Property.DateTime({
      displayName: 'Start Date',
      description: 'Project start date',
      required: false,
    }),
    end_date: Property.DateTime({
      displayName: 'End Date',
      description: 'Project end date',
      required: false,
    }),
    comment: Property.LongText({
      displayName: 'Comment',
      description: 'Project comment/description',
      required: false,
    }),
    pr_state_id: Property.Dropdown({
      auth: bexioAuth,
      displayName: 'Project Status',
      description: 'Status of the project',
      required: true,
      refreshers: [],
      options: async ({ auth }) => {
        if (!auth) {
          return {
            disabled: true,
            placeholder: 'Connect your Bexio account first',
            options: [],
          };
        }

        try {
          const client = new BexioClient(auth);
          const states = await client.get<Array<{ id: number; name: string }>>('/2.0/pr_project_state');

          return {
            disabled: false,
            options: states.map((state) => ({
              label: state.name,
              value: state.id,
            })),
          };
        } catch (error) {
          return {
            disabled: true,
            placeholder: 'Failed to load project statuses',
            options: [],
          };
        }
      },
    }),
    pr_project_type_id: Property.Dropdown({
      auth: bexioAuth,
      displayName: 'Project Type',
      description: 'Type of project',
      required: true,
      refreshers: [],
      options: async ({ auth }) => {
        if (!auth) {
          return {
            disabled: true,
            placeholder: 'Connect your Bexio account first',
            options: [],
          };
        }

        try {
          const client = new BexioClient(auth);
          const types = await client.get<Array<{ id: number; name: string }>>('/2.0/pr_project_type');

          return {
            disabled: false,
            options: types.map((type) => ({
              label: type.name,
              value: type.id,
            })),
          };
        } catch (error) {
          return {
            disabled: true,
            placeholder: 'Failed to load project types',
            options: [],
          };
        }
      },
    }),
    contact_id: Property.Dropdown({
      auth: bexioAuth,
      displayName: 'Contact',
      description: 'Contact associated with this project',
      required: true,
      refreshers: [],
      options: async ({ auth }) => {
        if (!auth) {
          return {
            disabled: true,
            placeholder: 'Connect your Bexio account first',
            options: [],
          };
        }

        try {
          const client = new BexioClient(auth);
          const contacts = await client.get<Array<{
            id: number;
            contact_type_id: number;
            name_1: string;
            name_2?: string | null;
            nr?: string | null;
          }>>('/2.0/contact');

          return {
            disabled: false,
            options: contacts.map((contact) => {
              const name = contact.name_2
                ? `${contact.name_2} ${contact.name_1}`
                : contact.name_1;
              const label = contact.nr ? `${name} (#${contact.nr})` : name;
              return {
                label,
                value: contact.id,
              };
            }),
          };
        } catch (error) {
          return {
            disabled: true,
            placeholder: 'Failed to load contacts',
            options: [],
          };
        }
      },
    }),
    contact_sub_id: Property.Dropdown({
      auth: bexioAuth,
      displayName: 'Contact Sub',
      description: 'Contact sub-address (optional)',
      required: false,
      refreshers: [],
      options: async ({ auth }) => {
        if (!auth) {
          return {
            disabled: true,
            placeholder: 'Connect your Bexio account first',
            options: [],
          };
        }

        try {
          const client = new BexioClient(auth);
          const contacts = await client.get<Array<{
            id: number;
            contact_type_id: number;
            name_1: string;
            name_2?: string | null;
            nr?: string | null;
          }>>('/2.0/contact');

          return {
            disabled: false,
            options: contacts.map((contact) => {
              const name = contact.name_2
                ? `${contact.name_2} ${contact.name_1}`
                : contact.name_1;
              const label = contact.nr ? `${name} (#${contact.nr})` : name;
              return {
                label,
                value: contact.id,
              };
            }),
          };
        } catch (error) {
          return {
            disabled: true,
            placeholder: 'Failed to load contacts',
            options: [],
          };
        }
      },
    }),
    pr_invoice_type_id: Property.StaticDropdown({
      displayName: 'Invoice Type',
      description: 'Type of invoicing for this project',
      required: false,
      options: {
        disabled: false,
        options: [
          { label: 'Hourly rate for client services', value: 1 },
          { label: 'Hourly rate for employee', value: 2 },
          { label: 'Hourly rate for project', value: 3 },
          { label: 'Fix price for project', value: 4 },
        ],
      },
    }),
    pr_invoice_type_amount: Property.ShortText({
      displayName: 'Invoice Type Amount',
      description: 'Amount for invoice type (only for hourly rate project or fix price)',
      required: false,
    }),
    pr_budget_type_id: Property.StaticDropdown({
      displayName: 'Budget Type',
      description: 'Type of budget for this project',
      required: false,
      options: {
        disabled: false,
        options: [
          { label: 'Total budget costs', value: 1 },
          { label: 'Total budget hours', value: 2 },
          { label: 'Budget for each client services', value: 3 },
          { label: 'Budget for each employee', value: 4 },
        ],
      },
    }),
    pr_budget_type_amount: Property.ShortText({
      displayName: 'Budget Type Amount',
      description: 'Amount for budget type (only for total budget costs or total budget hours)',
      required: false,
    }),
    user_id: Property.Dropdown({
      auth: bexioAuth,
      displayName: 'User',
      description: 'User responsible for this project',
      required: true,
      refreshers: [],
      options: async ({ auth }) => {
        if (!auth) {
          return {
            disabled: true,
            placeholder: 'Connect your Bexio account first',
            options: [],
          };
        }

        try {
          const client = new BexioClient(auth);
          const users = await client.get<Array<{
            id: number;
            firstname?: string | null;
            lastname?: string | null;
            email: string;
          }>>('/3.0/users');

          return {
            disabled: false,
            options: users.map((user) => {
              const name = user.firstname && user.lastname
                ? `${user.firstname} ${user.lastname}`
                : user.email;
              return {
                label: name,
                value: user.id,
              };
            }),
          };
        } catch (error) {
          return {
            disabled: true,
            placeholder: 'Failed to load users',
            options: [],
          };
        }
      },
    }),
  },
  async run({ auth, propsValue }) {
    const client = new BexioClient(auth);
    const props = propsValue;

    const requestBody: Record<string, unknown> = {
      name: props['name'],
      pr_state_id: props['pr_state_id'],
      pr_project_type_id: props['pr_project_type_id'],
      contact_id: props['contact_id'],
      user_id: props['user_id'],
    };

    if (props['document_nr']) {
      requestBody['document_nr'] = props['document_nr'];
    }
    if (props['start_date']) {
      // Convert DateTime to ISO string format expected by API
      const startDate = props['start_date'] as string;
      requestBody['start_date'] = startDate;
    }
    if (props['end_date']) {
      // Convert DateTime to ISO string format expected by API
      const endDate = props['end_date'] as string;
      requestBody['end_date'] = endDate;
    }
    if (props['comment']) {
      requestBody['comment'] = props['comment'];
    }
    if (props['contact_sub_id']) {
      requestBody['contact_sub_id'] = props['contact_sub_id'];
    }
    if (props['pr_invoice_type_id']) {
      requestBody['pr_invoice_type_id'] = props['pr_invoice_type_id'];
    }
    if (props['pr_invoice_type_amount']) {
      requestBody['pr_invoice_type_amount'] = props['pr_invoice_type_amount'];
    }
    if (props['pr_budget_type_id']) {
      requestBody['pr_budget_type_id'] = props['pr_budget_type_id'];
    }
    if (props['pr_budget_type_amount']) {
      requestBody['pr_budget_type_amount'] = props['pr_budget_type_amount'];
    }

    const response = await client.post<{
      id: number;
      uuid: string;
      nr: string;
      name: string;
      pr_state_id: number;
      pr_project_type_id: number;
      contact_id: number;
      user_id: number;
    }>('/2.0/pr_project', requestBody);

    return response;
  },
});

