package jira

import (
	jira "github.com/andygrunwald/go-jira"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/pkg/errors"
)

// resourceIssue is used to define a JIRA issue
func resourceIssue() *schema.Resource {
	return &schema.Resource{
		Create: resourceIssueCreate,
		Read:   resourceIssueRead,
		Update: resourceIssueUpdate,
		Delete: resourceIssueDelete,

		Schema: map[string]*schema.Schema{
			"assignee": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"reporter": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"issue_type": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"description": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Default:  "",
			},
			"summary": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"project_key": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			// Computed values
			"issue_key": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

// resourceIssueCreate creates a new jira issue using the jira api
func resourceIssueCreate(d *schema.ResourceData, m interface{}) error {
	config := m.(*Config)
	assignee := d.Get("assignee").(string)
	reporter := d.Get("reporter").(string)
	issueType := d.Get("issue_type").(string)
	description := d.Get("description").(string)
	summary := d.Get("summary").(string)
	projectKey := d.Get("project_key").(string)

	i := jira.Issue{
		Fields: &jira.IssueFields{
			Assignee: &jira.User{
				Name: assignee,
			},
			Reporter: &jira.User{
				Name: reporter,
			},
			Description: description,
			Type: jira.IssueType{
				Name: issueType,
			},
			Project: jira.Project{
				Key: projectKey,
			},
			Summary: summary,
		},
	}
	issue, _, err := config.jiraClient.Issue.Create(&i)
	if err != nil {
		return errors.Wrap(err, "creating jira issue failed")
	}

	d.SetId(issue.ID)

	return resourceIssueRead(d, m)
}

// resourceIssueRead reads issue details using jira api
func resourceIssueRead(d *schema.ResourceData, m interface{}) error {
	config := m.(*Config)

	issue, _, err := config.jiraClient.Issue.Get(d.Id(), nil)
	if err != nil {
		return errors.Wrap(err, "getting jira issue failed")
	}

	d.Set("assignee", issue.Fields.Assignee.Name)
	d.Set("reporter", issue.Fields.Reporter.Name)
	d.Set("issue_type", issue.Fields.Type.Name)
	if issue.Fields.Description != "" {
		d.Set("description", issue.Fields.Description)
	}
	d.Set("summary", issue.Fields.Summary)
	d.Set("project_key", issue.Fields.Project.Key)
	d.Set("issue_key", issue.Key)

	return nil
}

// resourceIssueUpdate updates jira issue using jira api
func resourceIssueUpdate(d *schema.ResourceData, m interface{}) error {
	config := m.(*Config)
	assignee := d.Get("assignee").(string)
	reporter := d.Get("reporter").(string)
	issueType := d.Get("issue_type").(string)
	description := d.Get("description").(string)
	summary := d.Get("summary").(string)
	projectKey := d.Get("project_key").(string)
	issueKey := d.Get("issue_key").(string)

	i := jira.Issue{
		Key: issueKey,
		ID:  d.Id(),
		Fields: &jira.IssueFields{
			Assignee: &jira.User{
				Name: assignee,
			},
			Reporter: &jira.User{
				Name: reporter,
			},
			Description: description,
			Type: jira.IssueType{
				Name: issueType,
			},
			Project: jira.Project{
				Key: projectKey,
			},
			Summary: summary,
		},
	}
	issue, _, err := config.jiraClient.Issue.Update(&i)
	if err != nil {
		return errors.Wrap(err, "updating jira issue failed: %s")
	}

	d.SetId(issue.ID)

	return resourceIssueRead(d, m)
}

// resourceIssueDelete deletes jira issue using the jira api
func resourceIssueDelete(d *schema.ResourceData, m interface{}) error {
	config := m.(*Config)

	id := d.Id()

	_, err := config.jiraClient.Issue.Delete(id)
	if err != nil {
		return errors.Wrap(err, "deleting jira issue failed")
	}
	return nil
}
