"""
This module defines the GraphQL schema for the Firefly Solar application.
It includes the types, queries, and resolvers needed to interact with the GraphQL API.

It imports the necessary GraphQL components and defines the schema with a query type that includes fields for portal users and status.
It also imports the resolvers that handle the logic for fetching data when queries are made.
"""

from graphql import (
    GraphQLSchema,
    GraphQLObjectType,
    GraphQLField,
    GraphQLString,
    GraphQLList,
    GraphQLNonNull,
    GraphQLID,
    GraphQLEnumType,
    GraphQLInputObjectType,
    GraphQLInputField,
    GraphQLBoolean,
    GraphQLArgument,
    GraphQLInt,  # ✅ ADD THIS
    GraphQLFloat,  # ✅ ADD THIS
)
from resolvers.query_resolvers import (
    get_all_tickets_for_user,
    get_comments_by_note_id,
    get_notes_by_lead_id,
    get_portal_users,
    get_status,
    get_all_users,
    me_resolver,
    get_all_customers,
    get_customer_by_id,
    get_missed_calls_by_dept,
    get_all_departments,
    get_all_tickets_for_department,
    get_all_notes,
    get_notes_by_customer_id,
    get_notes_by_job_id,
    get_all_leads,
    get_customer_view_by_customer_id,
    get_lead_home_information_by_lead_id,
    get_contact_points_by_lead_id,
    get_lead_metrics,
    get_managed_teams,
    get_team_members,
    get_lead_activity_by_lead_id,
)
from resolvers.mutation_resolvers import (
    create_comment_resolver,
    create_lead_resolver,
    login_resolver,
    create_account_resolver,
    google_login_resolver,
    logout_resolver,
    create_ticket_resolver,
    create_note_resolver,
    update_lead_by_id_resolver,
    update_lead_home_information_resolver,
    create_lead_contact_point_resolver,
    update_contact_point_resolver,
    create_team_resolver,
    add_team_member_resolver,
    remove_team_member_resolver,
    create_lead_file_uploads_resolver,
    get_equifax_soft_pull_resolver,
    create_equifax_loan_resolver,
    update_equifax_loan_resolver,
)

## TYPES ---------------------------------------------------------------------------
# Define the type for the data returned
PortalUserType = GraphQLObjectType(
    name="PortalUser",
    fields={
        "name": GraphQLField(GraphQLNonNull(GraphQLString)),
        "role": GraphQLField(GraphQLNonNull(GraphQLString)),
    },
)

roleType = GraphQLObjectType(
    name="Role",
    fields={
        "role_id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "role_name": GraphQLField(GraphQLNonNull(GraphQLString)),
    },
)
# Define the type for userInfo records
UserInfoType = GraphQLObjectType(
    name="UserInfo",
    fields={
        "id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "customerName": GraphQLField(GraphQLString),
        "userName": GraphQLField(GraphQLString),
        "contactType": GraphQLField(GraphQLString),
        "callDuration": GraphQLField(GraphQLString),
        "contactedDate": GraphQLField(GraphQLString),
        "outcome": GraphQLField(GraphQLString),
        "notes": GraphQLField(GraphQLString),
        "name": GraphQLField(GraphQLString),
        "phone": GraphQLField(GraphQLString),
        "email": GraphQLField(GraphQLString),
        "lastContacted": GraphQLField(GraphQLString),
        "status": GraphQLField(GraphQLString),
    },
)

AllUsersType = GraphQLObjectType(
    name="AllUsers",
    fields={
        "id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "name": GraphQLField(GraphQLNonNull(GraphQLString)),
        "email": GraphQLField(GraphQLNonNull(GraphQLString)),
        "status": GraphQLField(GraphQLNonNull(GraphQLString)),
        "dept_id": GraphQLField(GraphQLID),
        "roles": GraphQLField(GraphQLList(roleType)),  # ✅ role_id/role_name
    },
)


GetAllUsersReturnType = GraphQLNonNull(GraphQLList(GraphQLNonNull(AllUsersType)))

UserRoleType = GraphQLEnumType(
    name="UserRole",
    values={"ADMIN": "admin", "USER": "user", "SUPER_ADMIN": "super_admin"},
)

createUserType = GraphQLInputObjectType(
    name="CreateUser",
    fields={
        "userName": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "password": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "role": GraphQLInputField(UserRoleType),
    },
)

userLoginType = GraphQLObjectType(
    name="UserLogin",
    fields={
        "userName": GraphQLField(GraphQLNonNull(GraphQLString)),
        "passwordHash": GraphQLField(GraphQLNonNull(GraphQLString)),
    },
)

userLoginInputType = GraphQLInputObjectType(
    name="UserLoginInput",
    fields={
        "userName": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "passwordHash": GraphQLInputField(GraphQLNonNull(GraphQLString)),
    },
)

authenicatedUserResponseType = GraphQLObjectType(
    name="AuthenticatedUserResponse",
    fields={
        "id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "userName": GraphQLField(GraphQLNonNull(GraphQLString)),
        "role": GraphQLField(GraphQLNonNull(UserRoleType)),
        "lastLogin": GraphQLField(GraphQLString),
        "isActive": GraphQLField(GraphQLNonNull(GraphQLString)),
        "createdAt": GraphQLField(GraphQLString),
    },
)


loginResultType = GraphQLObjectType(
    name="LoginResult",
    fields={
        "user": GraphQLField(authenicatedUserResponseType),
        "error": GraphQLField(GraphQLString),
    },
)


googleLoginResultType = GraphQLObjectType(
    name="GoogleLoginResult",
    fields={
        "accessToken": GraphQLField(GraphQLNonNull(GraphQLString)),
        "user": GraphQLField(
            GraphQLObjectType(
                name="GoogleUser",
                fields={
                    "id": GraphQLField(GraphQLNonNull(GraphQLID)),
                    "email": GraphQLField(GraphQLNonNull(GraphQLString)),
                    "name": GraphQLField(GraphQLNonNull(GraphQLString)),
                    "roles": GraphQLField(GraphQLList(roleType)),
                    "dept_id": GraphQLField(GraphQLID),
                },
            )
        ),
    },
)

userType = GraphQLObjectType(
    name="User",
    fields={
        "id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "email": GraphQLField(GraphQLNonNull(GraphQLString)),
        "name": GraphQLField(GraphQLNonNull(GraphQLString)),
        "dept_id": GraphQLField(GraphQLID),
        "roles": GraphQLField(GraphQLList(roleType)),  # role_id/role_name
    },
)

customer_return_type = GraphQLObjectType(
    name="OneCustomerRecord",
    fields={
        "id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "first_name": GraphQLField(GraphQLNonNull(GraphQLString)),
        "last_name": GraphQLField(GraphQLNonNull(GraphQLString)),
        "address": GraphQLField(GraphQLNonNull(GraphQLString)),
        "email": GraphQLField(GraphQLString),
        "phone_number": GraphQLField(GraphQLString),
        "page_id": GraphQLField(GraphQLNonNull(GraphQLString)),
    },
)

all_customers_return_type = GraphQLList(
    GraphQLObjectType(
        name="CustomerRecord",
        fields={
            "id": GraphQLField(GraphQLNonNull(GraphQLID)),
            "first_name": GraphQLField(GraphQLNonNull(GraphQLString)),
            "last_name": GraphQLField(GraphQLString),
            "address": GraphQLField(GraphQLString),
            "email": GraphQLField(GraphQLString),
            "phone_number": GraphQLField(GraphQLString),
            "page_id": GraphQLField(GraphQLString),
        },
    )
)

action_type_call_actions = GraphQLEnumType(
    name="ActionType",
    values={
        "MISSED_CALL": "Missed Call",
        "VOICEMAIL": "Voicemail",
    },
)

status_call_actions = GraphQLEnumType(
    name="CallActionStatus",
    values={
        "OPEN": "Open",
        "COMPLETED": "Completed",
        "CANCELED": "Canceled",
        "IN_PROGRESS": "In Progress",
    },
)

priority_call_actions = GraphQLEnumType(
    name="CallActionPriority",
    values={
        "LOW": "Low",
        "NORMAL": "Normal",
        "HIGH": "High",
        "CRITICAL": "Critical",
    },
)

all_missed_calls_return_type = GraphQLList(
    GraphQLObjectType(
        name="CallAction",
        fields={
            "id": GraphQLField(GraphQLNonNull(GraphQLID)),
            "action_type": GraphQLField(action_type_call_actions),
            "status": GraphQLField(status_call_actions),
            "priority": GraphQLField(priority_call_actions),
            "telephony_session_id": GraphQLField(GraphQLString),
            "department_id": GraphQLField(GraphQLID),
            "customer_id": GraphQLField(GraphQLID),
            "phone_number": GraphQLField(GraphQLString),
            "summary": GraphQLField(GraphQLString),
            "occurred_at": GraphQLField(GraphQLString),
            "created_at": GraphQLField(GraphQLString),
            "updated_at": GraphQLField(GraphQLString),
            "assigned_user_id": GraphQLField(GraphQLID),
        },
    )
)

create_lead_input_type = GraphQLInputObjectType(
    name="CreateLeadInput",
    fields={
        "first_name": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "last_name": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "email": GraphQLInputField(GraphQLString),
        "phone_number": GraphQLInputField(GraphQLString),
        "phone_type": GraphQLInputField(GraphQLString),
        "communication_opted_out": GraphQLInputField(GraphQLBoolean),
        "address": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "lead_source": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "sub_lead_source": GraphQLInputField(GraphQLString),
        "home_depot_unique_id": GraphQLInputField(GraphQLString),
        "secondary_first_name": GraphQLInputField(GraphQLString),
        "secondary_last_name": GraphQLInputField(GraphQLString),
        "secondary_email": GraphQLInputField(GraphQLString),
        "secondary_phone_number": GraphQLInputField(GraphQLString),
        "secondary_phone_type": GraphQLInputField(GraphQLString),
    },
)

create_lead_home_information_input_type = GraphQLInputObjectType(
    name="CreateLeadHomeInformationInput",
    fields={
        "note_id": GraphQLInputField(GraphQLID),
        "appointment_time": GraphQLInputField(GraphQLString),
        "year_home_built": GraphQLInputField(GraphQLInt),
        "years_in_home": GraphQLInputField(GraphQLInt),
        "age_of_shingles_years": GraphQLInputField(GraphQLInt),
        "shingle_type": GraphQLInputField(GraphQLString),
        "plans_on_moving": GraphQLInputField(GraphQLBoolean),
        "moving_information": GraphQLInputField(GraphQLString),
        "has_detached_garage": GraphQLInputField(GraphQLBoolean),
        "has_panel_in_garage": GraphQLInputField(GraphQLBoolean),
        "has_subpanel": GraphQLInputField(GraphQLBoolean),
        "subpanel_location": GraphQLInputField(GraphQLString),
        "electrical_adders": GraphQLInputField(GraphQLBoolean),
        "c_source": GraphQLInputField(GraphQLString),
        "contact_source": GraphQLInputField(GraphQLString),
        "solar_form_completed": GraphQLInputField(GraphQLBoolean),
        "rural_property": GraphQLInputField(GraphQLBoolean),
        "gas_electrical_locations": GraphQLInputField(GraphQLString),
        "topography_details": GraphQLInputField(GraphQLString),
        "buried_lines_locations": GraphQLInputField(GraphQLString),
        "property_access_to_desired_solar_location": GraphQLInputField(GraphQLString),
        "how_to_access_desired_solar_location": GraphQLInputField(GraphQLString),
        "mounting_type": GraphQLInputField(GraphQLString),
    },
)

lead_home_information_type = GraphQLObjectType(
    name="LeadHomeInformation",
    fields={
        "id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "lead_id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "note_id": GraphQLField(GraphQLID),
        "appointment_time": GraphQLField(GraphQLString),
        "year_home_built": GraphQLField(GraphQLInt),
        "years_in_home": GraphQLField(GraphQLInt),
        "age_of_shingles_years": GraphQLField(GraphQLInt),
        "shingle_type": GraphQLField(GraphQLString),
        "plans_on_moving": GraphQLField(GraphQLBoolean),
        "moving_information": GraphQLField(GraphQLString),
        "has_detached_garage": GraphQLField(GraphQLBoolean),
        "has_panel_in_garage": GraphQLField(GraphQLBoolean),
        "has_subpanel": GraphQLField(GraphQLBoolean),
        "subpanel_location": GraphQLField(GraphQLString),
        "electrical_adders": GraphQLField(GraphQLBoolean),
        "c_source": GraphQLField(GraphQLString),
        "contact_source": GraphQLField(GraphQLString),
        "solar_form_completed": GraphQLField(GraphQLBoolean),
        "rural_property": GraphQLField(GraphQLBoolean),
        "gas_electrical_locations": GraphQLField(GraphQLString),
        "topography_details": GraphQLField(GraphQLString),
        "buried_lines_locations": GraphQLField(GraphQLString),
        "property_access_to_desired_solar_location": GraphQLField(GraphQLString),
        "how_to_access_desired_solar_location": GraphQLField(GraphQLString),
        "mounting_type": GraphQLField(GraphQLString),
    },
)


update_lead_home_information_input_type = GraphQLInputObjectType(
    name="UpdateLeadHomeInformationInput",
    fields={
        "id": GraphQLInputField(GraphQLNonNull(GraphQLID)),
        "lead_id": GraphQLInputField(GraphQLID),
        "note_id": GraphQLInputField(GraphQLID),
        "appointment_time": GraphQLInputField(GraphQLString),
        "year_home_built": GraphQLInputField(GraphQLInt),
        "years_in_home": GraphQLInputField(GraphQLInt),
        "age_of_shingles_years": GraphQLInputField(GraphQLInt),
        "shingle_type": GraphQLInputField(GraphQLString),
        "plans_on_moving": GraphQLInputField(GraphQLBoolean),
        "moving_information": GraphQLInputField(GraphQLString),
        "has_detached_garage": GraphQLInputField(GraphQLBoolean),
        "has_panel_in_garage": GraphQLInputField(GraphQLBoolean),
        "has_subpanel": GraphQLInputField(GraphQLBoolean),
        "subpanel_location": GraphQLInputField(GraphQLString),
        "electrical_adders": GraphQLInputField(GraphQLBoolean),
        "c_source": GraphQLInputField(GraphQLString),
        "contact_source": GraphQLInputField(GraphQLString),
        "solar_form_completed": GraphQLInputField(GraphQLBoolean),
        "rural_property": GraphQLInputField(GraphQLBoolean),
        "gas_electrical_locations": GraphQLInputField(GraphQLString),
        "topography_details": GraphQLInputField(GraphQLString),
        "buried_lines_locations": GraphQLInputField(GraphQLString),
        "property_access_to_desired_solar_location": GraphQLInputField(GraphQLString),
        "how_to_access_desired_solar_location": GraphQLInputField(GraphQLString),
        "mounting_type": GraphQLInputField(GraphQLString),
    },
)


update_lead_input_type = GraphQLInputObjectType(
    name="UpdateLeadInput",
    fields={
        "first_name": GraphQLInputField(GraphQLString),
        "last_name": GraphQLInputField(GraphQLString),
        "email": GraphQLInputField(GraphQLString),
        "phone_number": GraphQLInputField(GraphQLString),
        "phone_type": GraphQLInputField(GraphQLString),
        "communication_opted_out": GraphQLInputField(GraphQLBoolean),
        "address": GraphQLInputField(GraphQLString),
        "city": GraphQLInputField(GraphQLString),
        "state_province": GraphQLInputField(GraphQLString),
        "zip": GraphQLInputField(GraphQLString),
        "lead_source": GraphQLInputField(GraphQLString),
        "sub_lead_source": GraphQLInputField(GraphQLString),
        "source_id": GraphQLInputField(GraphQLString),
        "customer_id": GraphQLInputField(GraphQLID),
        "home_depot_unique_id": GraphQLInputField(GraphQLString),
        "secondary_first_name": GraphQLInputField(GraphQLString),
        "secondary_last_name": GraphQLInputField(GraphQLString),
        "secondary_email": GraphQLInputField(GraphQLString),
        "secondary_phone_number": GraphQLInputField(GraphQLString),
        "secondary_phone_type": GraphQLInputField(GraphQLString),
    },
)

comment = GraphQLObjectType(
    name="Comment",
    fields={
        "id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "note_id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "text": GraphQLField(GraphQLNonNull(GraphQLString)),
        "created_at": GraphQLField(GraphQLString),
        "created_by": GraphQLField(GraphQLNonNull(GraphQLID)),
        "created_by_name": GraphQLField(GraphQLString),  # New field for user's name
    },
)

create_comment_input_type = GraphQLInputObjectType(
    name="CreateCommentInput",
    fields={
        "note_id": GraphQLInputField(GraphQLNonNull(GraphQLID)),
        "text": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "created_by": GraphQLInputField(GraphQLNonNull(GraphQLID)),
    },
)


# Output Ticket type stays the same
ticket = GraphQLObjectType(
    name="Ticket",
    fields={
        "id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "created_by_user_id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "assigned_to_user_id": GraphQLField(GraphQLID),
        "department_id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "description": GraphQLField(GraphQLNonNull(GraphQLString)),
        "status": GraphQLField(GraphQLNonNull(GraphQLString)),
        "priority": GraphQLField(GraphQLNonNull(GraphQLString)),
        "assigned_at": GraphQLField(GraphQLString),
        "completed_at": GraphQLField(GraphQLString),
        "created_at": GraphQLField(GraphQLString),
        "updated_at": GraphQLField(GraphQLString),
    },
)

# ✅ Prefer list always returned, never null items
all_tickets_return_type = GraphQLNonNull(GraphQLList(GraphQLNonNull(ticket)))


CreateTicketInputType = GraphQLInputObjectType(
    name="CreateTicketInput",
    fields={
        "created_by_user_id": GraphQLInputField(GraphQLNonNull(GraphQLID)),
        "assigned_to_user_id": GraphQLInputField(GraphQLID),
        "department_id": GraphQLInputField(GraphQLNonNull(GraphQLID)),
        "description": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "status": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "priority": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        # include these only if your API allows clients to set them:
        "assigned_at": GraphQLInputField(GraphQLString),
        "completed_at": GraphQLInputField(GraphQLString),
    },
)

department = GraphQLObjectType(
    name="Department",
    fields={
        "id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "name": GraphQLField(GraphQLNonNull(GraphQLString)),
        "phone_number": GraphQLField(GraphQLString),
        "extension_number": GraphQLField(GraphQLString),
        "extension_id": GraphQLField(GraphQLID),
    },
)

all_departments_return_type = GraphQLList(department)

create_note_type = GraphQLInputObjectType(
    name="CreateNoteInput",
    fields={
        "note_type": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "title": GraphQLInputField(GraphQLString),
        "note_description": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "user_id": GraphQLInputField(GraphQLID),
        "customer_id": GraphQLInputField(GraphQLID),
        "ff_job_id": GraphQLInputField(GraphQLID),
        "lead_id": GraphQLInputField(GraphQLID),
    },
)

note = GraphQLObjectType(
    name="Note",
    fields={
        "id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "note_type": GraphQLField(GraphQLNonNull(GraphQLString)),
        "title": GraphQLField(GraphQLNonNull(GraphQLString)),
        "note_description": GraphQLField(GraphQLNonNull(GraphQLString)),
        "user_id": GraphQLField(GraphQLID),
        "customer_id": GraphQLField(GraphQLID),
        "ff_job_id": GraphQLField(GraphQLID),
        "created_at": GraphQLField(GraphQLString),
        "lead_id": GraphQLField(GraphQLID),
    },
)

note_with_user_name = GraphQLObjectType(
    name="NoteWithUserName",
    fields={
        "id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "note_type": GraphQLField(GraphQLNonNull(GraphQLString)),
        "title": GraphQLField(GraphQLNonNull(GraphQLString)),
        "note_description": GraphQLField(GraphQLNonNull(GraphQLString)),
        "user_id": GraphQLField(GraphQLID),
        "customer_id": GraphQLField(GraphQLID),
        "ff_job_id": GraphQLField(GraphQLID),
        "created_at": GraphQLField(GraphQLString),
        "lead_id": GraphQLField(GraphQLID),
        "created_by_name": GraphQLField(GraphQLString),  # New field for user's name
        "comment_count": GraphQLField(GraphQLInt),
    },
)

get_notes_by_lead_id_return_type = GraphQLList(note_with_user_name)

all_notes_return_type = GraphQLList(note)

lead = GraphQLObjectType(
    name="Lead",
    fields={
        "id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "first_name": GraphQLField(GraphQLString),
        "last_name": GraphQLField(GraphQLString),
        "email": GraphQLField(GraphQLString),
        "phone_number": GraphQLField(GraphQLString),
        "phone_type": GraphQLField(GraphQLString),
        "communication_opted_out": GraphQLField(GraphQLBoolean),
        "address": GraphQLField(GraphQLString),
        "lead_source": GraphQLField(GraphQLString),
        "sub_lead_source": GraphQLField(GraphQLString),
        "created_at": GraphQLField(GraphQLString),
        "updated_at": GraphQLField(GraphQLString),
        "source_id": GraphQLField(GraphQLID),
        "home_depot_unique_id": GraphQLField(GraphQLString),
        "secondary_first_name": GraphQLField(GraphQLString),
        "secondary_last_name": GraphQLField(GraphQLString),
        "secondary_email": GraphQLField(GraphQLString),
        "secondary_phone_number": GraphQLField(GraphQLString),
        "secondary_phone_type": GraphQLField(GraphQLString),
        "contact_points_count": GraphQLField(GraphQLInt),
    },
)
all_leads_return_type = GraphQLList(lead)

contact_point = GraphQLObjectType(
    name="ContactPoint",
    fields={
        "id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "lead_id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "created_at": GraphQLField(GraphQLString),
        "notes": GraphQLField(GraphQLString),
        "contact_type": GraphQLField(GraphQLString),
        "created_by": GraphQLField(GraphQLID),
        "created_by_name": GraphQLField(GraphQLString),
    },
)

get_contact_points_by_lead_id_return_type = GraphQLList(contact_point)

lead_activity = GraphQLObjectType(
    name="LeadActivity",
    fields={
        "id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "lead_id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "activity_type": GraphQLField(GraphQLNonNull(GraphQLString)),
        "activity_description": GraphQLField(GraphQLString),
        "created_by": GraphQLField(GraphQLID),
        "created_by_name": GraphQLField(GraphQLString),
        "created_at": GraphQLField(GraphQLString),
        "event_metadata": GraphQLField(GraphQLString),
    },
)

get_lead_activity_by_lead_id_return_type = GraphQLList(lead_activity)

create_lead_contact_point_input_type = GraphQLInputObjectType(
    name="CreateLeadContactPointInput",
    fields={
        "lead_id": GraphQLInputField(GraphQLNonNull(GraphQLID)),
        "notes": GraphQLInputField(GraphQLString),
        "contact_type": GraphQLInputField(GraphQLString),
        "created_by": GraphQLInputField(GraphQLID),
    },
)

create_lead_file_upload_input_type = GraphQLInputObjectType(
    name="CreateLeadFileUploadInput",
    fields={
        "lead_id": GraphQLInputField(GraphQLNonNull(GraphQLID)),
        "uploaded_by_user_id": GraphQLInputField(GraphQLNonNull(GraphQLID)),
        "slot": GraphQLInputField(GraphQLString),
        "filename": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "mime_type": GraphQLInputField(GraphQLString),
        "file_size_bytes": GraphQLInputField(GraphQLNonNull(GraphQLInt)),
        "content_base64": GraphQLInputField(GraphQLString),
    },
)

update_contact_point_input_type = GraphQLInputObjectType(
    name="UpdateContactPointInput",
    fields={
        "id": GraphQLInputField(GraphQLNonNull(GraphQLID)),
        "lead_id": GraphQLInputField(GraphQLID),
        "notes": GraphQLInputField(GraphQLString),
        "contact_type": GraphQLInputField(GraphQLString),
    },
)

rayze_soft_pull_input_type = GraphQLInputObjectType(
    name="RayzeSoftPullInput",
    fields={
        "reference_id": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "first_name": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "last_name": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "email": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "address": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "city": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "province": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "postal_code": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "date_of_birth": GraphQLInputField(GraphQLNonNull(GraphQLString)),
    },
)

equifax_transaction_input_type = GraphQLInputObjectType(
    name="EquifaxTransactionInput",
    fields={
        "loan_number": GraphQLInputField(GraphQLNonNull(GraphQLString)),
        "created_by_id": GraphQLInputField(GraphQLInt),
        "created_by_name": GraphQLInputField(GraphQLString),
    },
)

create_equifax_loan_input_type = GraphQLInputObjectType(
    name="CreateEquifaxLoanInput",
    fields={
        "lookup_hash": GraphQLInputField(GraphQLString),
        "loan_number": GraphQLInputField(GraphQLString),
        "customer_id": GraphQLInputField(GraphQLInt),
        "lead_id": GraphQLInputField(GraphQLInt),
        "loan_status": GraphQLInputField(GraphQLString),
        "first_name": GraphQLInputField(GraphQLString),
        "last_name": GraphQLInputField(GraphQLString),
        "email": GraphQLInputField(GraphQLString),
        "phone_number": GraphQLInputField(GraphQLString),
        "co_borrower_first_name": GraphQLInputField(GraphQLString),
        "co_borrower_last_name": GraphQLInputField(GraphQLString),
        "co_borrower_phone_number": GraphQLInputField(GraphQLString),
        "co_borrower_email": GraphQLInputField(GraphQLString),
        "co_borrower_address": GraphQLInputField(GraphQLString),
        "address_line_1": GraphQLInputField(GraphQLString),
        "postal_code": GraphQLInputField(GraphQLString),
        "date_of_birth": GraphQLInputField(GraphQLString),
        "city": GraphQLInputField(GraphQLString),
        "province": GraphQLInputField(GraphQLString),
        "system_cost": GraphQLInputField(GraphQLFloat),
        "available_approved_funds": GraphQLInputField(GraphQLFloat),
        "payments_past_due": GraphQLInputField(GraphQLBoolean),
        "created_by_id": GraphQLInputField(GraphQLInt),
        "created_by_name": GraphQLInputField(GraphQLString),
        "payment_frequency": GraphQLInputField(GraphQLString),
        "promo_id": GraphQLInputField(GraphQLInt),
        "amortization_period": GraphQLInputField(GraphQLString),
        "application_title": GraphQLInputField(GraphQLString),
        "purchase_category": GraphQLInputField(GraphQLString),
        "language_preference": GraphQLInputField(GraphQLString),
        "mailing_address": GraphQLInputField(GraphQLString),
        "project_address": GraphQLInputField(GraphQLString),
        "apt_unit_number": GraphQLInputField(GraphQLString),
        "has_consented_to_soft_pull": GraphQLInputField(GraphQLBoolean),
        "has_consented_to_hard_pull": GraphQLInputField(GraphQLBoolean),
    },
)

update_equifax_loan_input_type = GraphQLInputObjectType(
    name="UpdateEquifaxLoanInput",
    fields={
        "customer_id": GraphQLInputField(GraphQLInt),
        "lead_id": GraphQLInputField(GraphQLInt),
        "loan_status": GraphQLInputField(GraphQLString),
        "first_name": GraphQLInputField(GraphQLString),
        "last_name": GraphQLInputField(GraphQLString),
        "email": GraphQLInputField(GraphQLString),
        "phone_number": GraphQLInputField(GraphQLString),
        "co_borrower_first_name": GraphQLInputField(GraphQLString),
        "co_borrower_last_name": GraphQLInputField(GraphQLString),
        "co_borrower_phone_number": GraphQLInputField(GraphQLString),
        "co_borrower_email": GraphQLInputField(GraphQLString),
        "co_borrower_address": GraphQLInputField(GraphQLString),
        "address_line_1": GraphQLInputField(GraphQLString),
        "postal_code": GraphQLInputField(GraphQLString),
        "date_of_birth": GraphQLInputField(GraphQLString),
        "city": GraphQLInputField(GraphQLString),
        "province": GraphQLInputField(GraphQLString),
        "system_cost": GraphQLInputField(GraphQLFloat),
        "available_approved_funds": GraphQLInputField(GraphQLFloat),
        "payments_past_due": GraphQLInputField(GraphQLBoolean),
        "created_by_id": GraphQLInputField(GraphQLInt),
        "created_by_name": GraphQLInputField(GraphQLString),
        "payment_frequency": GraphQLInputField(GraphQLString),
        "promo_id": GraphQLInputField(GraphQLInt),
        "amortization_period": GraphQLInputField(GraphQLString),
        "application_title": GraphQLInputField(GraphQLString),
        "purchase_category": GraphQLInputField(GraphQLString),
        "language_preference": GraphQLInputField(GraphQLString),
        "mailing_address": GraphQLInputField(GraphQLString),
        "project_address": GraphQLInputField(GraphQLString),
        "apt_unit_number": GraphQLInputField(GraphQLString),
        "has_consented_to_soft_pull": GraphQLInputField(GraphQLBoolean),
        "has_consented_to_hard_pull": GraphQLInputField(GraphQLBoolean),
    },
)

rayze_soft_pull_result_type = GraphQLObjectType(
    name="RayzeSoftPullResult",
    fields={
        "transaction_id": GraphQLField(GraphQLInt),
        "transaction_result": GraphQLField(GraphQLString),
        "status_code": GraphQLField(GraphQLInt),
        "data": GraphQLField(GraphQLString),
        "error": GraphQLField(GraphQLString),
        "message": GraphQLField(GraphQLString),
    },
)

lead_metric_row = GraphQLObjectType(
    name="LeadMetricRow",
    fields={
        "lead_source": GraphQLField(GraphQLString),
        "sub_lead_source": GraphQLField(GraphQLString),
        "stage": GraphQLField(GraphQLString),
        "count": GraphQLField(GraphQLInt),
        "avg_touchpoints_to_appointment": GraphQLField(GraphQLFloat),
        "appointment_lead_counts": GraphQLField(GraphQLInt),
    },
)

team_type = GraphQLObjectType(
    name="Team",
    fields={
        "id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "name": GraphQLField(GraphQLNonNull(GraphQLString)),
        "manager_user_id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "member_count": GraphQLField(GraphQLNonNull(GraphQLInt)),
    },
)

team_member_type = GraphQLObjectType(
    name="TeamMember",
    fields={
        "user_id": GraphQLField(GraphQLNonNull(GraphQLID)),
        "name": GraphQLField(GraphQLNonNull(GraphQLString)),
        "email": GraphQLField(GraphQLNonNull(GraphQLString)),
    },
)


# --- Supporting types ------------------------------------------------------------

DocRefType = GraphQLObjectType(
    name="DocRef",
    fields={
        "name": GraphQLField(GraphQLString),
        "url": GraphQLField(GraphQLString),
        "mime_type": GraphQLField(GraphQLString),
        "created_at": GraphQLField(GraphQLString),
    },
)

# --- Main type -------------------------------------------------------------------

customer_view_type = GraphQLObjectType(
    name="CustomerView",
    fields={
        # DB identity
        "id": GraphQLField(GraphQLInt),
        "customer_id": GraphQLField(GraphQLInt),
        "job_number": GraphQLField(GraphQLString),
        # Customer fields
        "first_name": GraphQLField(GraphQLString),
        "last_name": GraphQLField(GraphQLString),
        "email": GraphQLField(GraphQLString),
        "phone_number": GraphQLField(GraphQLString),
        "address": GraphQLField(GraphQLString),
        "page_id": GraphQLField(GraphQLString),
        "customer_status": GraphQLField(GraphQLString),
        "last_contacted": GraphQLField(GraphQLString),  # datetime -> ISO string
        "system_size_kw": GraphQLField(GraphQLFloat),
        "inverter_type": GraphQLField(GraphQLString),
        "utility_provider": GraphQLField(GraphQLString),
        "quoted_price_cents": GraphQLField(GraphQLInt),
        "financing_type": GraphQLField(GraphQLString),
        "contract_id": GraphQLField(GraphQLString),
        "install_date_legacy": GraphQLField(GraphQLString),  # date -> ISO string
        # Job fields
        "job_status": GraphQLField(GraphQLString),
        "sold_date": GraphQLField(GraphQLString),  # date -> ISO string
        "municipality": GraphQLField(GraphQLString),
        "ahj": GraphQLField(GraphQLString),
        "setter_name": GraphQLField(GraphQLString),
        "closer_name": GraphQLField(GraphQLString),
        # JSON date arrays
        "install_dates": GraphQLField(GraphQLList(GraphQLString)),
        "service_dates": GraphQLField(GraphQLList(GraphQLString)),
        "inspection_dates": GraphQLField(GraphQLList(GraphQLString)),
        # JSON doc/media arrays
        "slds": GraphQLField(GraphQLList(DocRefType)),
        "contracts": GraphQLField(GraphQLList(DocRefType)),
        "proposals": GraphQLField(GraphQLList(DocRefType)),
        "closeout_package": GraphQLField(GraphQLList(DocRefType)),
        # JSON photo arrays
        "setter_photos": GraphQLField(GraphQLList(GraphQLString)),  # HttpUrl -> String
        "site_survey_photos": GraphQLField(
            GraphQLList(GraphQLString)
        ),  # HttpUrl -> String
        # DB timestamps
        "created_at": GraphQLField(GraphQLString),  # datetime -> ISO string
        "updated_at": GraphQLField(GraphQLString),  # datetime -> ISO string
    },
)
## --------------------------------------------------------------------------------

## QUERIES --------------------------------------------------------------------------
# Define the Query type with resolvers
QueryType = GraphQLObjectType(
    name="Query",
    fields={
        "portalUsers": GraphQLField(
            GraphQLNonNull(GraphQLList(GraphQLNonNull(PortalUserType))),
            resolve=get_portal_users,
        ),
        "getStatus": GraphQLField(
            GraphQLNonNull(GraphQLString),
            resolve=get_status,
        ),
        # "getAllUserInfo": GraphQLField(
        #     GraphQLNonNull(GraphQLList(GraphQLNonNull(UserInfoType))),
        #     resolve=get_all_users,
        # ),
        "me": GraphQLField(userType, resolve=me_resolver),
        "getAllCustomers": GraphQLField(
            GraphQLNonNull(all_customers_return_type), resolve=get_all_customers
        ),
        "getCustomerById": GraphQLField(
            customer_return_type,
            args={"id": GraphQLArgument(GraphQLNonNull(GraphQLID))},
            resolve=get_customer_by_id,
        ),
        "getMissedCallsByDept": GraphQLField(
            all_missed_calls_return_type,
            args={"dept_id": GraphQLArgument(GraphQLNonNull(GraphQLID))},
            resolve=get_missed_calls_by_dept,
        ),
        "getAllTicketsForUser": GraphQLField(
            all_tickets_return_type,
            args={
                "user_id": GraphQLArgument(GraphQLNonNull(GraphQLInt))
            },  # ✅ was GraphQLID
            resolve=get_all_tickets_for_user,
        ),
        "getAllUsers": GraphQLField(
            GetAllUsersReturnType,
            resolve=get_all_users,
        ),
        "getAllDepartments": GraphQLField(
            all_departments_return_type,
            resolve=get_all_departments,
        ),
        "getAllTicketsForDepartment": GraphQLField(
            all_tickets_return_type,
            args={
                "department_id": GraphQLArgument(GraphQLNonNull(GraphQLInt))
            },  # ✅ was GraphQLID
            resolve=get_all_tickets_for_department,
        ),
        "getAllNotes": GraphQLField(
            all_notes_return_type,
            resolve=get_all_notes,
        ),
        "getNotesByCustomerId": GraphQLField(
            all_notes_return_type,
            args={"customer_id": GraphQLArgument(GraphQLNonNull(GraphQLID))},
            resolve=get_notes_by_customer_id,
        ),
        "getNotesByJobId": GraphQLField(
            all_notes_return_type,
            args={"ff_job_id": GraphQLArgument(GraphQLNonNull(GraphQLID))},
            resolve=get_notes_by_job_id,
        ),
        "getAllLeads": GraphQLField(
            all_leads_return_type,
            resolve=get_all_leads,
        ),
        "getCustomerViewByCustomerId": GraphQLField(
            GraphQLList(customer_view_type),
            args={"customer_id": GraphQLArgument(GraphQLNonNull(GraphQLInt))},
            resolve=get_customer_view_by_customer_id,
        ),
        "getLeadHomeInformationByLeadId": GraphQLField(
            lead_home_information_type,
            args={"lead_id": GraphQLNonNull(GraphQLID)},
            resolve=get_lead_home_information_by_lead_id,
        ),
        "getCommentsByNoteId": GraphQLField(
            GraphQLList(comment),
            args={"note_id": GraphQLArgument(GraphQLNonNull(GraphQLID))},
            resolve=get_comments_by_note_id,
        ),
        "getNotesByLeadId": GraphQLField(
            get_notes_by_lead_id_return_type,
            args={"lead_id": GraphQLArgument(GraphQLNonNull(GraphQLID))},
            resolve=get_notes_by_lead_id,
        ),
        "getContactPointsByLeadId": GraphQLField(
            get_contact_points_by_lead_id_return_type,
            args={"lead_id": GraphQLArgument(GraphQLNonNull(GraphQLID))},
            resolve=get_contact_points_by_lead_id,
        ),
        "getLeadActivityByLeadId": GraphQLField(
            get_lead_activity_by_lead_id_return_type,
            args={
                "lead_id": GraphQLArgument(GraphQLNonNull(GraphQLID)),
                "limit": GraphQLArgument(GraphQLInt),
            },
            resolve=get_lead_activity_by_lead_id,
        ),
        "getLeadMetrics": GraphQLField(
            GraphQLList(lead_metric_row),
            args={
                "lead_source": GraphQLArgument(GraphQLString),
                "sub_lead_source": GraphQLArgument(GraphQLString),
            },
            resolve=get_lead_metrics,
        ),
        "getManagedTeams": GraphQLField(
            GraphQLList(team_type),
            resolve=get_managed_teams,
        ),
        "getTeamMembers": GraphQLField(
            GraphQLList(team_member_type),
            args={"team_id": GraphQLArgument(GraphQLNonNull(GraphQLID))},
            resolve=get_team_members,
        ),
    },
)
#
## --------------------------------------------------------------------------------

# MUTATIONS --------------------------------------------------------------------------

MutationType = GraphQLObjectType(
    name="Mutation",
    fields={
        "login": GraphQLField(
            GraphQLNonNull(loginResultType),  # Or your return type
            args={"userCredentials": GraphQLNonNull(userLoginInputType)},
            resolve=login_resolver,
        ),
        "createAccount": GraphQLField(
            GraphQLNonNull(
                GraphQLString
            ),  # Assuming you want to return the created user
            args={
                "createUserCredentials": GraphQLNonNull(createUserType)  # Default role
            },
            resolve=create_account_resolver,  # Import this resolver function
        ),
        "googleLogin": GraphQLField(
            GraphQLNonNull(googleLoginResultType),  # Or your return type
            args={"token": GraphQLNonNull(GraphQLString)},
            resolve=google_login_resolver,
        ),
        "logout": GraphQLField(GraphQLNonNull(GraphQLBoolean), resolve=logout_resolver),
        "createLead": GraphQLField(
            GraphQLNonNull(GraphQLID),
            args={
                "leadData": GraphQLNonNull(create_lead_input_type),
                "leadHomeInfoData": GraphQLArgument(
                    create_lead_home_information_input_type
                ),
            },
            resolve=create_lead_resolver,
        ),
        "createTicket": GraphQLField(
            GraphQLNonNull(GraphQLID),
            args={
                "ticketData": GraphQLArgument(GraphQLNonNull(CreateTicketInputType))
            },  # ✅ fixed
            resolve=create_ticket_resolver,
        ),
        "createNote": GraphQLField(
            GraphQLNonNull(GraphQLID),
            args={"noteData": GraphQLArgument(GraphQLNonNull(create_note_type))},
            resolve=create_note_resolver,
        ),
        "createComment": GraphQLField(
            GraphQLNonNull(GraphQLID),
            args={
                "commentData": GraphQLArgument(
                    GraphQLNonNull(create_comment_input_type)
                )
            },
            resolve=create_comment_resolver,
        ),
        "updateLeadById": GraphQLField(
            GraphQLNonNull(GraphQLBoolean),
            args={
                "leadId": GraphQLArgument(GraphQLNonNull(GraphQLID)),
                "leadData": GraphQLArgument(GraphQLNonNull(update_lead_input_type)),
            },
            resolve=update_lead_by_id_resolver,
        ),
        "updateLeadHomeInformation": GraphQLField(
            GraphQLNonNull(GraphQLBoolean),
            args={
                "homeInfoData": GraphQLArgument(
                    GraphQLNonNull(update_lead_home_information_input_type)
                )
            },
            resolve=update_lead_home_information_resolver,
        ),
        "createLeadContactPoint": GraphQLField(
            GraphQLNonNull(GraphQLID),
            args={
                "contactPointData": GraphQLArgument(
                    GraphQLNonNull(create_lead_contact_point_input_type)
                )
            },
            resolve=create_lead_contact_point_resolver,
        ),
        "updateLeadContactPoint": GraphQLField(
            GraphQLNonNull(GraphQLBoolean),
            args={
                "contactPointData": GraphQLArgument(
                    GraphQLNonNull(update_contact_point_input_type)
                )
            },
            resolve=update_contact_point_resolver,
        ),
        "createTeam": GraphQLField(
            GraphQLNonNull(GraphQLID),
            args={"name": GraphQLArgument(GraphQLNonNull(GraphQLString))},
            resolve=create_team_resolver,
        ),
        "addTeamMember": GraphQLField(
            GraphQLNonNull(GraphQLBoolean),
            args={
                "team_id": GraphQLArgument(GraphQLNonNull(GraphQLID)),
                "user_id": GraphQLArgument(GraphQLNonNull(GraphQLID)),
            },
            resolve=add_team_member_resolver,
        ),
        "removeTeamMember": GraphQLField(
            GraphQLNonNull(GraphQLBoolean),
            args={
                "team_id": GraphQLArgument(GraphQLNonNull(GraphQLID)),
                "user_id": GraphQLArgument(GraphQLNonNull(GraphQLID)),
            },
            resolve=remove_team_member_resolver,
        ),
        "createLeadFileUploads": GraphQLField(
            GraphQLNonNull(GraphQLBoolean),
            args={
                "upload_data": GraphQLArgument(
                    GraphQLNonNull(
                        GraphQLList(GraphQLNonNull(create_lead_file_upload_input_type))
                    )
                )
            },
            resolve=create_lead_file_uploads_resolver,
        ),
        "getEquifaxSoftPull": GraphQLField(
            GraphQLNonNull(rayze_soft_pull_result_type),
            args={
                "softPullData": GraphQLArgument(
                    GraphQLNonNull(rayze_soft_pull_input_type)
                ),
                "transactionData": GraphQLArgument(
                    GraphQLNonNull(equifax_transaction_input_type)
                ),
            },
            resolve=get_equifax_soft_pull_resolver,
        ),
        "createEquifaxLoan": GraphQLField(
            GraphQLNonNull(GraphQLID),
            args={"loan_data": GraphQLArgument(GraphQLNonNull(create_equifax_loan_input_type))},
            resolve=create_equifax_loan_resolver,
        ),
        "updateEquifaxLoan": GraphQLField(
            GraphQLNonNull(GraphQLBoolean),
            args={
                "loan_number": GraphQLArgument(GraphQLNonNull(GraphQLString)),
                "loan_data": GraphQLArgument(GraphQLNonNull(update_equifax_loan_input_type)),
            },
            resolve=update_equifax_loan_resolver,
        ),
    },
)


## --------------------------------------------------------------------------------

# Create the schema
schema = GraphQLSchema(query=QueryType, mutation=MutationType)
